Using Dependency Injection frameworks for classes with many dependencies?

First: Add the simple dependencies to your constructor as needed. There is no need to add every type to every constructor, just add the ones you need. Need another one, just expand the constructor.

Performance should not be a big thing as most of these types are likely to be singletons so already created after the first call. Do not use a static DI Container to create other objects. Instead add the DI Container to itself so it can resolve itself as a dependency.So something like this (assuming Unity for the moment) IUnityContainer container = new UnityContainer(); container.

RegisterInstance(container) This way you can just add a dependency on IUnityContainer and use that to create expensive or seldom needed objects. The main advantage is that it is much easier when unit testing as there are no static dependencies Second: No need to pass in a factory class. Using the technique above you can use the DI container itself to create expensive objects when needed Three: Add the DI container and the light singleton dependencies to the main form and create the rest through the DI container as needed.

Takes a little more code but as you said the startup cost and memory consumption of the mainform would go through the roof if you create everything at startup time.

First: Add the simple dependencies to your constructor as needed. There is no need to add every type to every constructor, just add the ones you need. Need another one, just expand the constructor.

Performance should not be a big thing as most of these types are likely to be singletons so already created after the first call. Do not use a static DI Container to create other objects. Instead add the DI Container to itself so it can resolve itself as a dependency.So something like this (assuming Unity for the moment) IUnityContainer container = new UnityContainer(); container.

RegisterInstance(container); This way you can just add a dependency on IUnityContainer and use that to create expensive or seldom needed objects. The main advantage is that it is much easier when unit testing as there are no static dependencies. Second: No need to pass in a factory class.

Using the technique above you can use the DI container itself to create expensive objects when needed. Three: Add the DI container and the light singleton dependencies to the main form and create the rest through the DI container as needed. Takes a little more code but as you said the startup cost and memory consumption of the mainform would go through the roof if you create everything at startup time.

6 IMHO, Injecting IContainer is similarly bad idea like opaque usage of ServiceLocator because it (also) hides the dependencies preventing effective refactoring and black box testing. – Nikola Malovic Oct 16 '09 at 9:19.

Well, while you can do this as described in other answers I believe there is more important thing to be answered regarding your example and that is that you are probably violating SRP principle with class having many dependencies. What I would consider in your example is breaking up the class in couple of more coherent classes with focused concerns and thus the number of their dependencies would fall down. Nikola's law of SRP and DI "Any class having more then 3 dependencies should be questioned for SRP violation" (To avoid lengthy answer, I posted in detail my answers on IoC and SRP blog post).

3 fair enough, but as I commented on your blog - I was introducing IoC to a project with almost 1 million lines of code. I can't fix all violations of SRP overnight. We're using Unity now, and things are slowly moving in the right direction.

– Mark Heath Oct 17 '09 at 7:53.

First: You could inject these objects, when needed, as members instead of in the constructor. That way you don't have to make changes to the constructor as your usage changes, and you also don't need to use a static. Second: Pass in some sort of builder or factory.

Third: Any class should only have those dependencies that it itself requires. Subclasses should be injected with their own specific dependencies.

I have a similar case related to the "expensive to create and might be used", where in my own IoC implementation, I'm adding automagic support for factory services. Basically, instead of this: public SomeService(ICDBurner burner) { } you would do this: public SomeService(IServiceFactory burnerFactory) { } ICDBurner burner = burnerFactory.Create(); This has two advantages: Behind the scenes, the service container that resolved your service is also used to resolve the burner, if and when it is requested This alleviates the concerns I've seen before in this kind of case where the typical way would be to inject the service container itself as a parameter to your service, basically saying "This service requires other services, but I'm not going to easily tell you which ones" The factory object is rather easy to make, and solves a lot of problems. Here's my factory class: using System; using System.Collections.

Generic; using System. Linq; using System. Text; using LVK.IoC.

Interfaces; using System. Diagnostics; namespace LVK. IoC { /// /// This class is used to implement for all /// services automatically.

/// DebuggerDisplay("AutoServiceFactory (Type={typeof(T)}, Policy={Policy})") internal class AutoServiceFactory : ServiceBase, IServiceFactory { #region Private Fields DebuggerBrowsable(DebuggerBrowsableState. Never) private readonly String _Policy; #endregion #region Construction & Destruction /// /// Initializes a new instance of the class. /// /// The service container involved.

/// The policy to use when resolving the service. /// is null. Public AutoServiceFactory(IServiceContainer serviceContainer, String policy) : base(serviceContainer) { _Policy = policy; } /// /// Initializes a new instance of the class.

/// /// The service container involved. /// is null. Public AutoServiceFactory(IServiceContainer serviceContainer) : this(serviceContainer, null) { // Do nothing here } #endregion #region Public Properties /// /// Gets the policy that will be used when the service is resolved.

/// public String Policy { get { return _Policy; } } #endregion #region IServiceFactory Members /// /// Constructs a new service of the correct type and returns it. /// /// The created service. Public IService Create() { return MyServiceContainer.

Resolve(_Policy); } #endregion } } Basically, when I build the service container from my service container builder class, all service registrations are automatically given another co-service, implementing IServiceFactory for that service, unless the programmer has explicitly registered on him/her-self for that service. The above service is then used, with one parameter specifying the policy (which can be null if policies aren't used). This allows me to do this: var builder = new ServiceContainerBuilder(); builder.Register() .From.ConcreteType(); using (var container = builder.Build()) { using (var factory = container.Resolve()) { using (var service = factory.Instance.Create()) { service.Instance.

DoSomethingAwesomeHere(); } } } Of course, a more typical use would be with your CD Burner object. In the above code I would resolve the service instead of course, but it's an illustration of what happens. So with your cd burner service instead: var builder = new ServiceContainerBuilder(); builder.Register() .From.ConcreteType(); builder.Register() .From.ConcreteType(); // constructor used in the top of answer using (var container = builder.Build()) { using (var service = container.Resolve()) { service.Instance.DoSomethingHere(); } } inside the service, you could now have a service, a factory service, which knows how to resolve your cd burner service upon request.

This is useful for the following reasons: You might want to resolve more than one service at the same time (burn two discs simultaneously? ) You might not need it, and it could be costly to create, so you only resolve it if needed You might need to resolve, dispose, resolve, dispose, multiple times, instead of hoping/trying to clean up an existing service instance You're also flagging in your constructor which services you need and which ones you might need Here's two at the same time: using (var service1 = container.Resolve()) using (var service2 = container.Resolve()) { service1.Instance.DoSomethingHere(); service2.Instance.DoSomethingHere(); } Here's two after each other, not reusing the same service: using (var service = container.Resolve()) { service.Instance.DoSomethingHere(); } using (var service = container.Resolve()) { service.Instance. DoSomethingElseHere(); }.

I'm not sure I'd like that, but, well, it's a possibility. Alternatively, you might like to use the new IServiceLocator common interface (blogs.msdn.com/gblock/archive/2008/10/02...) instead of injecting the dependencies? Second: You could use setter injection for the optional/on-demand dependencies?

I think I would go for injecting factories and new up from there on-demand.

To partially answer my first question, I've just found a blog post by Jeremy Miller, showing how Structure Map and setter injection can be used to auto-populate public properties of your objects. He uses ILogger as an example: var container = new Container(r => { r. FillAllPropertiesOfType().

TheDefault.Is . ConstructedBy(context => new Logger(context. ParentType)); }); This means that any classes with an ILogger property, e.g. : public class ClassWithLogger { public ILogger Logger { get; set; } } public class ClassWithLogger2 { public ILogger Logger { get; set; } } will have their Logger property automatically set up when constructed: container.GetInstance().

Most, if not all, popular IOC container have this capability. In Unity you need to decorate a property with the DependencyAttribute. This is still all done at the same time so there is no lazy loading involved here.

– Maurice Oct 14 '08 at 16:57 yes I imagine that most of them can do this. I do like that StructureMap doesn't require attributes for this, which reduces the need for all assemblies to reference the IOC dlls directly. As for lazy loading, I'm still looking for an elegant solution.

– Mark Heath Oct 14 '08 at 20:07 Having to have a public settor for the Logger is inviting desaster, isn't it? – David Schmitt Nov 14 '08 at 16:04.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions