ASP.NET Core option dependency in constructor - c#

I'm using ASP.NET Core and I'm attempting to create a resolvable class which has an optional parameter:
public class Foo
{
public Foo() : this(null)
{}
public Foo(IValidator<FooEntity> validator)
{
}
}
I've created two constructors for this object so that if a dependency isn't found, I would assume it would just fall back to the default constructor.
However when I run my application I receive this error
Additional information: Unable to resolve service for type 'FluentValidation.IValidator`1[FooEntity]' while attempting to activate 'Foo'
I know there is probably a way to manually resolve the construction of the Foo object. But I would prefer not to do that because I will have to do this for every class that I create without a validator.
Does anyone know how to configure ASP.NET Core DI to fall back to a different constructor if the dependency is not found?
EDIT
Sorry, I should of been a bit more clear before.
This Foo class I'm referring to in really a base class for a CRUD Service, which will be used over and over again.
I'm looking for a generic solution which doesn't require me to configure each Service I create each time.
So using a lambda to resolve this is not an option, The null object pattern seems feasible but I can't comprehend how to write a generic one in which I won't have to configure for each service

I think its general behavior of Containers to resolve the constructor with the most parameters.
Basically what AddTransient does is the following:
services.AddTransient<Foo>();
//equals to:
services.AddTransient<Foo>(c=> new Foo(c.GetService<IValidator<FooEntity>()));
So you can register it yourself like this:
services.AddTransient<Foo>(c=> new Foo());
At this point in the startup class you should know if IValidator<FooEntity> has been registered. Or, if you are using reflection add this logic to your reflection code.
Difference
The difference between the 2 options is that with the first option is that the lambda function to resolve the class is created on startup. + if you change the constructor no code needs to be changed elsewhere.
If you create the lambda yourself this lambda is compiled on build, so theoretically startup should be faster (I have not tested this).
Great mindset
A great mindset is to own the libraries you are using. In Visual studio/Resharper you can decompile source-code, or you can find the repositories on github nowadays.
There you can see the source code, you can see how the services parameters is 'compiled' to the IServiceProvider (see BuildServiceProvider() method, it will give you alot of insight.)
Also look at:
ServiceDescriptor, Your type registration.
Service, the one that resolves the type.
Solution
best way to do it is this, (sorry for psuedo code but i have no editor at hand).
getTypes()
.Where(x=> x.EndsWith("Entity") //lets get some types by logic
.Select(x=> typeof(IValidator<>).MakeGeneric(x)) //turn IValidator into IValidator<T>
.Where(x=> !services.IsRegistered(x))
.Each(x=> services.Add(x, c=> null)) //register value null for IValidator<T>

You need to register the IValidator<T> first:
var services = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
services.AddTransient<IValidator<FooEntity>, RealValidator<FooEntity>>();
services.AddTransient<Foo>();
var serviceProvider = services.BuildServiceProvider();
var validator = serviceProvider.GetService<IValidator<FooEntity>>();
var foo = serviceProvider.GetService<Foo>();
Assert.NotNull(validator);
Assert.NotNull(foo);

Related

SimpleInjector ctor injection mix registered types and simple values

How do I register types which take another registered type as a parameter and also simple types (like an integer)?
public interface IDeviceManager
{
// implementation omitted.
}
public class DeviceManager : IDeviceManager
{
public DeviceManager(IDeviceConfigRepository configRepo, int cacheTimeout)
{
// implementation omitted
}
}
I do have a container registration for the IDeviceConfigRepository. That's ok. But how do I create an instance of DeviceManager with the configured dependency and passing along an integer of my choice in composition root?
I thought about creating a factory.
public class DeviceManagerFactory : IDeviceManagerFactory
{
private readonly Container _container;
public DeviceManagerFactory(Container container)
{
_container = container;
}
public DeviceManager Create(int minutes)
{
var configRepo = _container.GetInstance<IDeviceConfigurationRepository>();
return new DeviceManager(configRepo, minutes);
}
}
This is pretty simple.
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
public class ExampleClassUsingDeviceManager
{
private readonly DeviceManager _deviceManager;
public ExampleClassUsingDeviceManager(DeviceManager deviceManager, ...)
{
_deviceManage = deviceManager;
}
// actions...
}
For this to work and to avoid circular dependencies I would probably have to move the factory from the "application" project (as opposed to class libraries) where the composition root is to the project where the DeviceManager is implemented.
Is that OK? It would of course mean passing around the container.
Any other solutions to this?
EDIT
In the same project for other types I am using parameter objects to inject configuration into my object graph. This works OK since I only have one class instance per parameter object type. If I had to inject different parameter object instances (for example MongoDbRepositoryOptions) into different class instances (for example MongoDbRepository) I would have to use some kind of named registration - which SimpleInjector doesn't support. Even though I only have one integer the parameter object pattern would solve my problem. But I'm not too happy about this pattern knowing it will break as soon as I have multiple instances of the consuming class (i.e. MongoDbRepository).
Example:
MongoDbRepositoryOptions options = new MongoDbRepositoryOptions();
MongoDbRepositoryOptions.CollectionName = "config";
MongoDbRepositoryOptions.ConnectionString = "mongodb://localhost:27017";
MongoDbRepositoryOptions.DatabaseName = "dev";
container.RegisterSingleton<MongoDbRepositoryOptions>(options);
container.RegisterSingleton<IDeviceConfigurationRepository, MongoDbRepository>();
I am excited to hear how you deal best with configurations done at composition root.
Letting your DeviceManagerFactory depend on Container is okay, as long as that factory implementation is part of your Composition Root.
Another option is to inject the IDeviceConfigRepository into the DeviceManagerFactory, this way you can construct a DeviceManager without the need to access the container:
public class DeviceManagerFactory : IDeviceManagerFactory {
private readonly IDeviceConfigurationRepository _repository;
public DeviceManagerFactory(IDeviceConfigurationRepository repository) {
_repository = repository;
}
public DeviceManager Create(int minutes) {
return new DeviceManager(_repository, minutes);
}
}
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
In general I would say that factories are usually the wrong abstraction, since they complicate the consumer instead of simplifying them. So you should typically depend on the service abstraction itself (instead of depending on a factory abstraction that can produces service abstraction implementations), or you should inject some sort of proxy or mediator that completely hides the existence of the service abstraction from point of view of the consumer.
#DavidL points at my blog post about runtime data. I'm unsure though whether the cacheTimeout is runtime data, although you seem to be using it as such, since you are passing it in into the Create method of the factory. But we're missing some context here, to determine what's going on. My blog post still stands though, if it is runtime data, it's an anti-pattern and in that case you should
pass runtime data through method calls of the API
or
retrieve runtime data from specific abstractions that allow resolving runtime data.
UPDATE
In case the value you are using is an application constant, that is read through the configuration file, and doesn't change during lifetime of the application, it is perfectly fine to inject it through the constructor. In that case it is not a runtime value. There is also no need for a factory.
There are multiple ways to register this in Simple Injector, for instance you can use a delegate to register the DeviceManager class:
container.Register<DeviceManager>(() => new DeviceManager(
container.GetInstance<IDeviceConfigRepository>(),
cacheTimeout: 15));
Downside of this approach is that you lose the ability of Simple Injector to auto-wire the type for you, and you disable Simple Injector's ability to verify, diagnose and visualize the object graph for you. Sometimes this is fine, while other times it is not.
The problem here is that Simple Injector blocks the registration of primitive types (because they cause ambiguity) while not presenting you with a clean way to make the registration. We are considering (finally) adding such feature in v4, but that doesn't really address your current needs.
Simple Injector doesn't easily allow you to specify a primitive dependency, while letting the container auto-wire the rest. Simple Injector's IDependencyInjectionBehavior abstraction allows you to override the default behavior (which is to disallow doing this). This is described here, but I usually advice against doing this, because it is usually requires quite a lot of code.
There are basically two options here:
Abstract the specific logic that deals with this caching out of the class and wrap it in a new class. This class will have just the cacheTimeout as its dependency. This is of course only useful when there actually is logical to abstract and is usually only logical when you are injecting that primitive value into multiple consumers. For instance, instead of injecting a connectionstring into multiple classes, you're probably better of injecting an IConnectionFactory into those classes instead.
Wrap the cacheTimeout value into a complex data container specific for the consuming class. This enables you to register that type, since it resolves the ambiguity issue. In fact, this is what you yourself are already suggesting and I think this is a really good thing to do. Since those values are constant at runtime, it is fine to register that DTO as singleton, but make sure to make it immutable. When you give each consumer its own data object, you won't have to register multiple instances of those, since they are unique. Btw, although named registations aren't supported, you can make conditional or contextual registrations using RegisterConditional and there are other ways to achieve named registrations with Simple Injector, but again, I don't think you really need that here.

Why is a type registered twice when lifetime manager is specified?

I'm using Unity's Register by convention mechanism in the following scenario:
public interface IInterface { }
public class Implementation : IInterface { }
Given Implementation class and its interface I'm running RegisterTypes in the following way:
unityContainer.RegisterTypes(
new[] { typeof(Implementation) },
WithMappings.FromAllInterfaces,
WithName.Default,
WithLifetime.ContainerControlled);
After this call, unitContainer contains three registrations:
IUnityContainer -> IUnityContainer (ok)
IInterface -> Implementation (ok)
Implementation -> Implementation (???)
When I change the call as follows:
unityContainer.RegisterTypes(
new[] { typeof(Implementation) },
WithMappings.FromAllInterfaces,
WithName.Default);
The container contains only two registrations:
IUnityContainer -> IUnityContainer (ok)
IInterface -> Implementation (ok)
(this is the desired behaviour).
After peeking into Unity's source code, I've noticed that there is some misunderstanding about how IUnityContainer.RegisterType should work.
The RegisterTypes method works as follows (the comments indicate what are the values in the scenarios presented above):
foreach (var type in types)
{
var fromTypes = getFromTypes(type); // { IInterface }
var name = getName(type); // null
var lifetimeManager = getLifetimeManager(type); // null or ContainerControlled
var injectionMembers = getInjectionMembers(type).ToArray(); // null
RegisterTypeMappings(container, overwriteExistingMappings, type, name, fromTypes, mappings);
if (lifetimeManager != null || injectionMembers.Length > 0)
{
container.RegisterType(type, name, lifetimeManager, injectionMembers); // !
}
}
Because fromTypes is not empty, the RegisterTypeMappings adds one type mapping: IInterface -> Implementation (correct).
Then, in case when lifetimeManager is not null, the code attempts to change the lifetime manager with the following call:
container.RegisterType(type, name, lifetimeManager, injectionMembers);
This function's name is completely misleading, because the documentation clearly states that:
RegisterType a LifetimeManager for the given type and name with the container. No type mapping is performed for this type.
Unfortunately, not only the name is misleading but the documentation is wrong. When debugging this code, I've noticed, that when there is no mapping from type (Implementation in the scenarios presented above), it is added (as type -> type) and that's why we end up with three registrations in the first scenario.
I've downloaded Unity's sources to fix the problem, but I've found the following unit test:
[TestMethod]
public void RegistersMappingAndImplementationTypeWithLifetimeAndMixedInjectionMembers()
{
var container = new UnityContainer();
container.RegisterTypes(new[] { typeof(MockLogger) }, getName: t => "name", getFromTypes: t => t.GetTypeInfo().ImplementedInterfaces, getLifetimeManager: t => new ContainerControlledLifetimeManager());
var registrations = container.Registrations.Where(r => r.MappedToType == typeof(MockLogger)).ToArray();
Assert.AreEqual(2, registrations.Length);
// ...
- which is almost exactly my case, and leads to my question:
Why is this expected? Is it a conceptual mistake, a unit test created to match existing behaviour but not necessarily correct, or am I missing something important?
I'm using Unity v4.0.30319.
We would need to reach out to the original developers to be sure, but this is what I can only assume as to why it was coded to be this way...
Unity has a feature that allows concrete classes to be resolved even though the type has not been registered. In this scenario, Unity must make the assumption that you want the default lifetime manager (transient) and no injection members for that concrete type. If you don't like those default policies, then you need to register the concrete type yourself and specify your customization.
So following that train of thought, when you call RegisterTypes and you do specify a lifetime manager and/or an injection member, then Unity makes the assumption that you want that behavior when resolving by the interface and by the concrete type. But if you do not specify those policies, then Unity doesn't need the concrete registration because it will fall back to the default behavior when resolving the concrete type.
The only other explanation that I can come up with is for the sake of plugins. InjectionMember is extensible, so Unity thinks you could be passing in a custom behavior for a plugin. And it therefore makes the assumption that you might want that custom behavior for the plugin to be applied to both the interface and the concrete when you are registering by convention.
I understand you are running into this issue while attempting to unit test your application bootstrap. I'm assuming you are testing to ensure the types you register and only those types are registered. This is breaking your tests because some tests find this extra concrete registration.
From a unit test perspective, I would argue that you are going beyond the scope of what you are attempting to test. If you start using plugins, there will be quite a few other registrations that start appearing (like interception policies and behaviors). That will just add to the problem you are seeing now because of the way you are testing. I would recommend you change your tests to ensure only a white-list of types are registered and ignore everything else. Having the concrete (or other additional registrations) is benign to your application.
(e.g. put your interfaces in the white-list and assert each one of those is registered and ignore the fact that the concrete is registered)
This behavior was fixed in version 5.2.1, as explained in this article:
Now all information passed to Unity during registration is stored with
FromType instead of ToType. So registering type like this:
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
creates just one registration ILogger and associates LifetimeManager
and all provided InjectionMemebers with it. At this point MockLogger
is still unregistered.
One reason that I can think of for the current behavior is that it reuses the existing Unity functionality/implementation and makes the registration by convention feature fairly easy to implement.
The existing Unity implementation that I'm thinking of is the separation of type mapping and build plan into different policies so if you are working on Unity source code that would be a common way to think about things. Also, from what I've read in the past, the Registrations property seems like it was thought of as a second class citizen and not intended to be used for much more than debugging so having another registration might not have seemed to be a big deal. Perhaps those two points put together were part of the decision?
Besides the extra item in the Registrations collections the feature is working in this case.
Then, in case when lifetimeManager is not null, the code attempts to change the lifetime manager with the following call
The RegisterTypes method doesn't actually set a LifetimeManager. If no LifetimeManager is specified then the concrete target type is not explicitly registered and Unity relies on the internal default behavior when creating the object (in this case a default LifetimeManager of TransientLifetimeManager).
But if anything is specified that could potentially override the defaults (i.e. a LifetimeManager or InjectionMembers) then the concrete type will be explicitly registered.
It should be possible to get Registration by Convention to work without the extra registration. However, there are some complexities to consider. If a concrete type implements many interfaces there could be multiple mapping registrations for a concrete type but each registration will need it's own lifetime manager instance (they can't be reused). So you could create new lifetime manager instances for each mapping registration but (I believe) only the last lifetime manager would be used. So to avoid unnecessary object creation perhaps only assign the lifetime manager on the last type mapping? That's just one scenario that occurred to me -- there are a variety of scenarios and combinations to consider.
So I think the current implementation is an easy way to implement the feature without having to specifically handle any edge cases with the only side effect being the extra registration. I would guess that was probably part of the thinking at the time (but I wasn't there so it's just a guess).

Ninject Multiple Type Constructor

I have started to use Ninject today because Structuremap let me down big time.
I hit an issue when I began registering the same types with the same interfaces but I have have named them (as shown below).
kernel.Bind<IDataContextAsync>().To<DbGeoContext>().InRequestScope().Named("DbGeoContext");
kernel.Bind<IDataContextAsync>().To<DbEspContext>().InRequestScope().Named("DbEspContext");
IParameter geoUnitOfWorkDbContext = new ConstructorArgument("dataContext", kernel.Get<IDataContextAsync>("DbGeoContext"));
IParameter espUnitOfWorkDbContext = new ConstructorArgument("dataContext", kernel.Get<IDataContextAsync>("DbEspContext"));
kernel.Bind<IUnitOfWorkAsync>().To<UnitOfWork>().Named("UnitOfWorkGeoContext").WithConstructorArgument(geoUnitOfWorkDbContext);
kernel.Bind<IUnitOfWorkAsync>().To<UnitOfWork>().Named("UnitOfWorkEspContext").WithConstructorArgument(espUnitOfWorkDbContext);
**Fails here with: Error activating IDataContextAsync
More than one matching bindings are available.**
var t1 = kernel.Get("UnitOfWorkGeoContext");
var t2 = kernel.Get("UnitOfWorkEspContext");
Could someone help me figure out what is going on here and how to fix it?
I understand at runtime Ninject wont be able to figure out which instance to inject, but I though this was what the 'Named' instances was for?
Thanks
When using Ninject to target multiple implementations of the same interface, you need to do so with the .Named call as you have done. But you also need to add the Named attribute on the constructor so that Ninject know which implementation to resolve.
As shown here:
https://github.com/ninject/ninject/wiki/Contextual-Binding#simple-constrained-resolution-named-bindings
Example
class SomeClassThatConsumesOneOfYourImplementations
{
public SomeClassThatConsumesOneOfYourImplementations(
[Named("DbGeoContext")] IDataContextAsync context)
{
// Constructor logic...
}
}

Unity suddenly fails to create class when I added an interface

In the process of decoupling some code and I extracted an interface for one of our classes, and mapped it using Unity like so
Container.RegisterType<IUserAuthorizationBC, UserAuthorizationBC>(
new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<PolicyInjectionBehavior>());
As you can see the class is UserAuthorizationBC and the interface is of course IUserAuthorizationBC. Once i did this I began to get an error in a class that I thought would not have mattered. The ctor for the class that now gives an error is as follows
public RoleAuthorizationService(IDataContractFactory factory,
UserAuthorizationBC businessProcessor)
: base(factory, businessProcessor)
{
_authBC = businessProcessor;
}
As you can see I haven't refactored it yet, I haven't even touched it, it was set up to get a concrete instance of UserAuthorizationBC and whoever created it is also injecting an IDataContractFactory which I did find mapped in our code base as you can see in following code snippet.
Container.RegisterType<IDataContractFactory, DefaultDataContractFactory>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>());
I get an error from unity as follows
Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the
dependency failed, type =
"HumanArc.Compass.Shared.Interfaces.Service.IRoleAuthorizationService",
name = "(none)".
Exception occurred while: Calling constructor Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior(Microsoft.Practices.Unity.InterceptionExtension.CurrentInterceptionRequest
interceptionRequest,
Microsoft.Practices.Unity.InterceptionExtension.InjectionPolicy[]
policies, Microsoft.Practices.Unity.IUnityContainer container).
Exception is: ArgumentException - Type passed must be an interface.
Now if I go comment out my mapping for IUserAuthorizationBC it will work fine again. I have no idea why.
actually I don't know why it ever works because if you look at the DefaultDataContractFactory it uses all generics which I would assume would always fail to resolve as at the time the unity doesn't know the type of T - see the class below.
public class DefaultDataContractFactory : IDataContractFactory
{
public DefaultDataContractFactory();
public virtual T Create<T>();
public virtual object Create(Type type);
public virtual Example<T> CreateExample<T>();
protected Type CreateFactoryType(Type instanceType);
}
So to sum things up there are two questions.
How does it even work in the first place before I added an interface for the IUserAuthorizationBC class and then added the mapping for unity - I would think that the IDataContractFactory would always blow it up.
Since it does work if I comment out the container mapping for IUserAuthorizationBC why does it stop working when I uncomment it - I would have thought it wouldn't make a bit of difference as this particular class always has been injected with a concrete instance of the UserAuthorizationBC
I thought I understood dependency injection fairly well - especially with unity but I am clearly missing the boat here.
I was going to make this a comment, but it's too long. Maybe your Unity container is configured for convention-based registrations, so your explicit registration is confusing matters. The IDataContractFactory/DefaultDataContractFactory pair needs to be explicity registered because the names don't follow the prescribed convention.
See if you have something like this in your code:
// This will register all types with a ISample/Sample naming convention
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default);
Prerequisite
Take a look at Interception using Unity. It looks like you are using interception with policy injection. Two conditions need to be met in order for a method to be intercepted. The policy needs to match on the method / type. And the type needs to opt-in to interception in the Unity registration by selecting an interceptor (InterfaceInterceptor, VirtualMethodInterceptor, or TransparentProxyInterceptor).
Answers
Commenting out that registration effectively opted-out that type from using interception.
You opted-in to interception but you told Unity to use interface interception. You are not resolving an interface, so it doesn't know how to generate a proxy for interception.
Possible solutions
Leave the registration as-is with the InterfaceInterceptor and update all constructors to use your new interface instead of the concrete type.
Change your new IUserAuthorizationBC registration to use VirtualMethodInterceptor and update any methods you want to be able to be intercepted to be virtual.
Change your new IUserAuthorizationBC registration to not specify an interceptor to effectively opt-out of interception.

Strategy for using command line args with Unity DI?

I'm using the Unity framework to inject a ConfigurationProvider into some of my classes via the following interface:
interface IConfigurationProvider<T>{
T GetConfiguration();
}
then, in my bootstrapper with Unity,
container.RegisterType(typeof (IConfigurationProvider<DongleConfiguration>),
typeof (DongleConfigurationProvider));
This has been a good strategy up until now & has allowed me to define different config providers for various implementations & tests. Now, I'd like one of the providers to use command line arguments to set up a config object, which requires me to pass along the args parameter to the ctor:
class ProblematicConfigurationProvider : IConfigurationProvider<ProblematicConfiguration> {
...
public ProblematicConfigurationProvider(string[] args) { ... }
...
}
I've read that I can use ParameterOverride to supply an optional ctor argument as such:
var configObj = container.Resolve<IConfigurationProvider<ProblematicConfiguration>>(new ParameterOverride("args", args));
However, I'm using DI "all the way" and relying on the container to resolve dependencies down the line after resolving RootObject or whatever my top level class is. My question is, how can I now use the configObj object I've just resolved if it's buried somewhere down deep in my dependency graph? How can I use a resolved object in another call to Resolve? Would it be through a similar use of ParameterOverride? Is there a way to set up the param override somewhere & have Unity use it without actually instantiating configObj?
I would do this differently. Add a CommandLineArguments class to your project, which just wraps the command line arguments. As part of your container initialization, register that with the container:
container.RegisterInstance(new CommandLineArguments(args));
Then your ConfigurationProvider should have a dependency of CommandLineArguments, not string[]. From there, it should just resolve everything naturally "all the way down" without using the parameter overrides.
Since your command line arguments aren't going to change, this makes it a lot simpler in my opinion.
Note: I use the CommandLineArguments type because it's a lot more descriptive of what's going on. You could register the string[] directly into the container, but that would feel a little wierd to me, and possibly inject you command line arguments somewhere you don't expect.

Categories

Resources