Ninject Multiple Type Constructor - c#

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...
}
}

Related

ASP.NET Core option dependency in constructor

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);

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.

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.

How can I pass a runtime parameter to a previously registered factory method using castle windsor?

I have a reporting MVC application that uses Castle Windsor.
On application start up (in global.asax) all of the types are registered and then each subsequent request to the application resolves the relevant report type and windsor automatically handles the dependencies.
I need to switch one of the dependant types for another depending on a parameter passed in on the request.
How can I achieve this?
I have registered a factory method with windsor to handle the resolution of the switchable types but as this is registered on application start how can I pass a parameter to the factory method when the parameter is only available on a later request?
If I try registering the factory for each request it works on the first request but then complains on all subsequent requests that the factory is already registered. Unregistering the factory after each request doesnt sound like the right thing to be doing.
When you need to resolve types at runtime, the normal solution is to inject a factory that can make the decision at the appropriate time:
public class ReportFactory: IReportFactory {
IReport CreateReport(bool useDefault) {
if (useDefault) {
return new DefaultReport();
} else {
return new UnusualReport();
}
}
}
Classes that previously required an IReport should demand an IReportFactory instead.
You definitely don't want to go modifying your container on a per-request basis. That's a recipe for disaster.
You've got two options. The first is to use HttpContext.Current inside the factory method.
IWhatever CreateWhatever() {
if (HttpContext.Current.Request["parameter"] == "value-for-other-whatever")
return new FirstWhatever();
return DefaultWhatever();
}
The other (better) option would be to inject a factory type that resolves the correct implementation, rather than having the container do it for you.
public class WhateverFactory : IWhateverFactory {
public IWhatever GetWhatever(string parameter) {
if(parameter == "value for other whatever")
return new OtherWhatever();
return new DefaultWhatever();
}
}
Your controller would then take an instance of the factory, and would let the factory make the decision of which type to instantiate.
Use TypedFactoryFacility for your factory.
You can take two appraoches:
Have a factory with two methods and utilise default convention it uses for locating the component:
With default convention, if you have a component registered with name "CustomFoo" the 2nd method would resolve that component, whereas the first one would get the default one.
public interface IFooFactory
{
IFoo GetFoo(...arguments);
IFoo GetCustomFoo(..arguments);
void ReleaseFoo(IFoo foo);
}
Use custom selector and encapsulate the selection logic there.
Have come across an article on Mike Hadlow's blog that uses a delegate registered with Windsor to return one of a number of named type registrations...
So basically the Windsor registration might look something like this...
container
.Register(
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2003>().Named("word2003"),
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2007>().Named("word2007"),
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterPdf>().Named("pdf"),
Component.For<Func<string, IReportFormatter>>().Instance(container.Resolve<IReportFormatter>),
Component.For<Foo>());
and the Foo constructor would take a parameter of the delegate type
Foo(Func<string, IReportFormatter> reportFormatterFactory)
now when Windsor resolves Foo, reportFormatterFactory is not resolved to an implementation of IReportFormatter instead it simply holds a reference to the container.Resolve method...
container.Resolve<IReportFormatter>(string)
that can later be used to get the correct IReportFormatter by calling...
reportFormatterFactory("word2007");
Perhaps not as easy to understand as registering a factory but does away with the need for the factory class.

How do you make a Generic Generic Factory?

I am working on a client (Silverlight) interface to a collection of webmethod. And I am trying to avoid writing any custom code for every webmethod. So I have created a ServiceCall<TResult> to handle each call, TResult specifies the return type of the service (I use XmlSerializer to create the returned instance). The client class exposes a function matching each webmethod, and all that function has to do is to create a new instance of ServiceCall<TResult>, with the TResult specified as the expected return type of the method.
And that works just fine.
I am also using Ninject (dependency injector) to try and keep everything independent. Ninject supports open generics, whichs works out great with my ServiceCall<TResult>.
But it also means that I'm injecting a reference to the Ninject container. Which hides the dependency on ServiceCall<TResult> being bound to the container. So I would like to instead inject a factory for creating my ServiceCall<TResult> instances. Which is not tricky, but I would like to make it a generic generic factory. Meaning I would like to have something like Factory<T<>> which would have a method public T<TU> Createinstance<TU>().
But I have no idea how I could create generic class with a type parameter that is itself an open genric.
Is it event posible in .Net? - Or do I have to create a specific ServiceCallFactory?
Edit:
I am using interfaces for the dependencies, but there's no need to mix them into the question here, so I edited that out of the question.
In responce to Timwi:
The common way to use dependency injection (DI) is to bind an interface to your implementation, only the container knows of these bindings. You then code up against the interfaces instead. This brings a ton of advantages. More than I can mention here.
Anyway it also rules out the static classes (since that would be a dependency on a specific class). Instead I'll instruct the container (Ninject in this case) to always hand me the same instance for the factory interface, in a singleton like behavior.
This rules out the public static class Factory<T> option, because it is static, and if it is not static I would need to now every type of T I'm gonna use, somewhat defeating the purpose of having a generic class.
The suggestion of having a non-generic class with a "totally generic" method (as in I pass in ServiceCall<MyResult> instead of just MyResult), is what more or less what I am doing now (minus the static class part). The Ninject container has an Get method that work like your second suggestion.
The problem with this is two part; firstly it makes my code directly dependent on one container (Ninject), but this is not really that big a problem to me. What does annoy me is that if you look at me Client from the outside, you'll only see a dependency on Ninject. You wont know until you run try to make a call that client needs an implementation of ServiceCall registered with Ninject to work.
But if the Client contructor took a parameter of type Factory>, then it would much clearer.
In any case I would think this would be a common issue, so either there a common solution, or it is not a common issue and I am trying to do something stupid ;)
I am still not that into dependency injection, so that may very well be the case.
Is this what you are looking for: Generic Factory Pattern
namespace GenericFactoryPatternTestApp
{
public class Factory< T >
{
private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >();
public Factory()
{
Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes();
foreach (Type type in types)
{
if (!typeof (T).IsAssignableFrom(type) || type == typeof (T))
{
// Incorrect type
continue;
}
// Add the type
_factoryDictionary.Add(type.Name, type);
}
}
public T Create< V >(params object[] args)
{
return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args);
}
}
}
So if I understand you right, you’d have a class looking a bit like this:
public static class Factory<T<>>
{
public static T<TU> CreateInstance<TU>() { /* ... */ }
}
and then you’d call it how? Like this?
var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>();
What stops you from simply declaring the factory like this...
public static class Factory<T>
{
public static T CreateInstance() { /* ... */ }
}
... or this ...
public static class Factory
{
public static T CreateInstance<T>() { /* ... */ }
}
... and then generating your instance like this?
var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance();
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>();
I’m sorry if I’m being dumb, but I’d probably need to know how Ninject works and how it allows you to pass in a factory.

Categories

Resources