I'm using C# and Unity Dependency Injection for developing a MVVM application in WPF. I'm looking for a cleanest solution for a following problem.
Some of my classes are parametrized with enums, for example, I have a class AudioChannelViewModel (let's call it for short A) and I want to register two instances of the class, one for Channel.Left and one for Channel.Right. This alone is not a problem, because I register those instances by naming them in RegisterType and then referring to them later by [Dependency(name)] attribute.
Moreover, A depends on some other classes, lets call them Dep1, Dep2 and Dep3. To perform the initialization of A, I must have ALL of my dependencies and the information about the Channel.
I tried to use the following strategies:
Property injection of Dep1, Dep2 and Dep3 and setting A's Channel in constructor by RegisterType with InjectionConstructor parameter. But how should I know when A is ready to be initialized? AFAIK I cannot assume anything about the property injection order.
Constructor injection of all four items. It would be IMHO the cleanest solution, as I would be able to perform initialization in constructor. But I'm unable to get this working in Unity. Registering A with InjectionConstructor param for Channel throws an exception, and registering with four InjectionConstructor params seems ugly.
Constructor injection of Dep1, Dep2 and Dep3 and property injection of Channel. Then I can initialize my class in the Channel setter. It works for this case, but what if A would be parametrized by more than one property? Then I wouldn't know when A is fully built up and ready for initialization.
How should the initialization be performed? Or maybe I'm making things overly complicated.
You don't say exactly what the exception was that you observed in strategy #2, but this is the approach I would be using (given your other requirements for being able to other initialisation having had all the dependencies successfully resolved). I suspect the problem is that you aren't providing a 'value' for all of the arguments of the constructor... InjectionConstructor assumes the constructor you want is the one matching the types of the values provided to the InjectionConstructor.
E.g. if you want to register a constructor for such a class...
public class AudioChannelViewModel {
public AudioChannelViewModel(Channel channel, Dep1 dep1, Dep2 dep2, Dep3 dep3) {
...
}
}
You should register it thus...
container.RegisterType<AudioChannelViewModel>("left",
new InjectionConstructor(Channel.Left,
typeof(Dep1), typeof(Dep2), typeof(Dep3)));
container.RegisterType<AudioChannelViewModel>("right",
new InjectionConstructor(Channel.Right,
typeof(Dep1), typeof(Dep2), typeof(Dep3)));
Unity will use the provided value for the first argument (a Channel enum value) and will then resolve the Dep1, Dep2 and Dep3 instances. You can also use ResolvedParameter<T> as an argument to InjectionConstructor if there were specific named instances of Dep1, Dep2 or Dep3 that you require.
Just providing Channel.Left or Channel.Right alone is insufficient, as Unity will believe it is being asked to use a constructor with just a Channel argument.
Or; if you HAVE already tried that and it isn't working... maybe Unity doesn't support enums in this instance (pun intended).
This MSDN page might shine some more light on the issue.
Related
I want to let Ninject resolve an instance of T based on a specific enum input value.
I have read about Ninject's factory extension, but I couldn't find any example having the factory resolve a specific class based on an enum.
Each class derives from a base class and that derived class has several, different interfaces that Ninject also has to resolve.
For example this is how the interface should look like:
public interface IProcessFactory
{
T Create<T>(ProcessIndex processIndex) where T : BaseProcess;
}
How can this be achieved ?
This is not supported out of the box. You can customize it by writing your own implementation of IInstanceProvider(also see ninject Wiki entry. Then configure it for your specific factory:
kernel.Bind<IFooFactory>()
.ToFactory(() => new MyCustomInstanceProvider());
Or alternatively, if you want to change the behavior of all .ToFactory() bindings: Rebind IInstanceProvider after loading Ninject.Extensions.Factory:
kernel.Rebind<IInstanceProvider>().To<MyCustomInstanceProvider>();
However, if it's not something you need often i would consider manually writing a factory implementation # composition root.
Anyway, in both cases you'll need to know how to create a conditional binding. Ninject calls it Contextual Binding.
One method is to use Binding-Metadata:
const string EnumKey = "EnumKey";
Bind<IFoo>().To<AFoo>()
.WithMetadata(EnumKey, MyEnum.A);
IResolutionRoot.Get<IFoo>(x => x.Get<MyEnum>(EnumKey) == MyEnum.A);
Another way would be to create a custom IParameter and use in a conditional binding:
Bind<IFoo>().To<AFoo>()
.When(x => x.Parameters.OfType<MyParameter>().Single().Value == A);
There are several options available to implement AbstractFactory using DI (Ninject).
After analyzing the options, I came up with the solution provided by Mark Seemann, see http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
The Container Based Factory solution is the one I chose, because:
Performance: on demand DI resolve on request, no instances loaded in the constructor
Easy for refactor: when we want to replace the current DI framework (Ninject) to a much better performer with (almost or even better) featureset, the only place to change are the calls inside the factory and not in the NinjectModules/Composition Root.
See also at SO:
Simple Injector:Factory classes that need to create classes with dependencies
I've got a lot of implementations of a specific generic interface and would like to resolve all of these implementations in the constructor. Of course, I can just add every implementation in the constructor. This will cause the constructor to have over 30 parameters, which isn't very nice to look and develop at.
While doing some research on the matter I discovered it's possible to inject an IEnumerable of an interface in the constructor, somewhat like this IEnumerable<IScriptExecution> scriptExecutionImplementations
This is what I'm searching for, but I need it to be like so:
public TheConstructor(IEnumerable<IScriptExecution<T>> scriptExecutionImplementations)
{}
Is it possible to inject all the IScriptExecution<T> in the constructor, using Autofac?
The following is an excerpt from my registration class:
builder.RegisterType<Library.ShardManager.Execution.DataScript.Users>().As<IScriptExecution<DBUser>>();
builder.RegisterType<Library.ShardManager.Execution.DataScript.Companies>().As<IScriptExecution<DBCompany>>();
Note: I don't think I need to use the Open Generics, because I already know the types and you can't use open generics in a constructor.
As requested by Jim Bolla in the comment section, an example on how I want to use this.
At the moment I've got this constructor:
public MoveShardletData(Guid shardletId, ShardLocation oldLocation, ShardLocation newLocation, ILog log,
IScriptCreator<DBAnalyticsInvitation> scriptAnalyticsInvitation, IScriptCreator<DBAnalyticsPromotion> scriptAnalyticsPromotion,
IScriptCreator<DBAnalyticsRetailerSubscriptionModule> scriptAnalyticsRetailerSubscriptionModule, IScriptCreator<DBAnalyticsRetailerSubscription> scriptAnalyticsRetailerSubscription, //and the list goes on...
The piece of code where I want to use the IScriptCreator<T> objects looks a bit like this:
var analyticsInvitations = GetTheAnalyticsInvitationObjects(someLocalVariableInTheCurrentScope)
var script = scriptAnalyticsInvitation.Insert(analyticsInvitations);
sb.Append(script);
//With all IScriptCreator<T> objects listed here in the same fashion.
It would be nice if this could be done in a loop. Because of the someLocalVariableInTheCurrentScope it's a bit hard to extract this piece of code.
The collection analyticsInvitations is the type T. If I can access the Autofac container I can probably resolve the correct IScriptCreator<T> manually, but that's cheating thus not advised.
I have a 3rd party class library. One of the classes in that library, has a constructor with multiple overrides.
I want to tell Unity to create the class, using a constructor with fewer parameters (by default, it selects the one with the most number of parameters). How can I do this?
I know I can use InjectionFactory, but I prefer to let Unity create the object for me, than writing a delegate for it. Also if I had access to the source I could probably label the desired constructor with InjectionConstructor, but I don't. So what would be my other option?
Since you cannot use InjectionConstructorAttribute (as you mentioned, the library is not yours), you can use the InjectionConstructor class (not an attribute). You will need to call Resolve yourself to make sure Unity builds up the constructor parameters. Something like this:
IUnityContainer c = new UnityContainer()
.RegisterType<IStuff, GoodStuff>()
.RegisterType<StuffUser>(new InjectionConstructor(c.Resolve<IStuff>()));
I'm working on a project that's using the MS Application Blocks. I see the 'Unity' dll is available to me. It's version 1.1 by the way. How can I use dependency injection here?
I have a class
public class ScheduleDataDetailsDC
{
public int ScheduleID;
public List<ScheduleRateLineItem> MinRateList;
public List<ScheduleRateLineItem> MaxRateList;
public List<ScheduleRateLineItem> VotRateList;
public List<ScheduleLOSRateDC> LosRateList;
public List<ScheduleRateParamsDC> RateParams;
}
So when I new it up I am doing this...
new ScheduleDataDetailsDC{
LosRateList = new List<ScheduleLOSRateDC>()
, MaxRateList = new List<ScheduleRateLineItemDC>()
, MinRateList = new List<ScheduleRateLineItemDC>()
, RateParams = new List<ScheduleRateParamsDC>()
, VotRateList = new List<ScheduleRateLineItemDC>()
}
Can Unity 1.1 Help me in anyway here? I would like to just be able to use var x = new ScheduleDetailsDC(), and those 5 inner lists be initialized for me. Can Unity do anything for me here? Please note I've never used DI before.
Thanks for any pointers,
~ck in San Diego
The best thing to do would be to initialise the lists in the constructor and deny direct access to them from other classes by making them into properties:
public class ScheduleDataDetailsDC
{
public ScheduleDataDetailsDC()
{
this.MinRateList = new List<ScheduleRateLineItem>();
//inialise other lists
}
public List<ScheduleRateLineItem> MinRateList { get; private set; }
...
}
It doesn't seem as though dependency injection can really be of use here since the class seems to be a simple data container, although it's difficult to tell without more context.
Yes Unity can help you, but I think it's not the case. You can just initialize your lists incide your object giving them default instances, Unity as any other IoC container shouldn't be used as a simple object builder (despite it could).
I'm not sure specifically what the details of the 1.1 release of Unity are, but generally speaking whenever you are using an Inversion of Control Container, you have to go through the following steps:
Register the types your IoC container (Unity in your case) knows about. This includes all of the main types that you plan to request, plus all of the dependent types. In your case you will need to let it know about ScheduleDataDetailsDC, and what, exactly needs to go into each of the lists that are considered dependencies
Your types should specify all of the required dependencies as constructor arguments. This is what the IoC Container will look at to determine what needs to be injected. If you have optional dependencies then you can use Property Injection to support that (if your IoC container supports it, which I think Unity does)
You must request an instance of your registered type from the container. How exactly you do this depends on you container. There should be a method like Get<T>() or Resolve<T>. Generally your going to request instances of the "Highest Level" classes, i.e the ones that are used somewhere near the entry point for your software. If you do this, and you have applied Dependency Injection for all dependent classes down the line (and you've correctly registered all of the dependent types) you should get an object with all of it's dependencies supplied, and likewise all of that objects dependencies should be supplied, and on down the line.
You also tend to see Interfaces used in conjunction with IoC a lot since you can bind a concrete type to the interface type, and then specify that interface as your dependency. This allows you to apply business rules and configuration values during the binding process that will give you the ability to use different concrete implementations in cases where you would need to do such a thing.
So given all of this, it's hard to say exactly what would be involved in utilizing Unity in the situation you've outlined above. Firstly you would need to register ScheduleDataDetailsDC, but to get the dependencies in place you would also need to register each of the List types, or more specifically each concrete object that would go in each list (and then, of course all of the dependencies for those classes). Since I'm not really sure what the roles of those lists are, it's hard for me to say how you could go about doing that (or even if you could go about doing that).
So I started this new project, and I was trying to incorporate all the new design principles I was reading about, namely trying to make things loosely coupled, testable, and following some patterns.
So I then ran into the issue of having to pass too many factories/managers into my classes constructor, which led me into Dependancy injection.
public class SomeClass
{
public SomeClass(IDBFactory factory, IOrderManager orderManager, ....)
}
So if I use ninject, from what I understand, I would then bind a particular implementation to the class.
So what is going on behind the scenes?
NInject will, whenever I instantiate SomeClass, it will bind the implementation that I defined in the config file?
i.e.
I do:
ISomeClass sc = NInject.Get<ISomeClass>();
and ninject will do:
new SomeClassImpl(pass in all the implementaitons in the constructor)
correct?
I don't know NInject, but most DI Containers support Auto-Wiring, which works this way:
When you request ISomeClass, it looks through its list of all registered types. Using this list, it discovers that the desired implementation of ISomClass is SomeClass.
It will use SomeClass' constructor to create an instance (perhaps using Activator.CreateInstance), so it uses Reflection to figure out which paramters are required.
For each paramameter, it looks at the type and repeats step 1-2 for each.
Thus, the process may be recursive, but in the end, you should end up with a fully populated object graph where all dependencies are satisfied.