How to use factory with Dependecy Injection without using Service Locator pattern

I have a GUI application. In it, I allow the user to choose from the list of algorithms provided by the container. Each algorithm will be launched as a background task in a different view. I need to support multiple instances of this view and support multiple instances of the same algorithm. This view will also be provided by the container. The algorithm also has a state.

So, I have a case where I need to instantiate my view and algorithm and bind them at runtime. I do not have static anchor points for these instances, so I cannot use the usual injection tools (constructor or property injection). I do not want to call new , and I do not want to use the container as a Service locator .

I solved this in Castle.Windsor with a typed Factory facility , but I had to deal with factories throughout my application. The Factory design was also a bit weird because I had to return my instances to Factory when I was with them.

Now I am studying the use of NInject, because so far the learning curve and intro-documents have been much better, and I would like to offer a container for my team. But for such a scenario, I think I would have to write my own factories and directly access the kernel to resolve new instances (Service Locator built into the factory), as well as add Factory methods to my registration code.

Is there a general way to solve this problem, or is it just a problem due to which Dependency Injection was not designed for a standalone solution?


Clarification:

I said in the comments that I needed a specific answer for Ninject, and I got this. And thank you very much :) In real life here, I probably just use the pragmatic solutions that have been proposed.

But I was looking for my question, providing my framework as a specific problem. I was hoping for a more purely fundamental answer to the question in my title.

Is there a pure-DI method that allows the user to start new instances of components at runtime? Or do all such implementations use the container as a service locator or require a certain “quirk” for the container (for example, built-in Factory support, ala Castle.Windsor or the Ninject Factory rate of fire), and not use only aspects of the “pure” DI?

I just heard this word from the Java world, and I don’t really understand what it means - so forgive me :) Is that what I was looking for some kind of "indentation"?

+3
dependency-injection ninject factory-pattern
source share
3 answers

Best of all you create a factory interface like this

 public interface IFooFactory { IFoo CreateFoo(int someParameter); } 

For Ninject 2.3 see https://github.com/ninject/ninject.extensions.factory and let it be implemented by Ninject by adding the following configuration.

 Bind<IFooFactory>().AsFactory(); 

For 2.2, do the implementation yourself. This implementation is part of the container configuration, not part of your implementations.

 public class FooFactory: IFooFactory { private IKernel kernel; public FooFactory(IKernel kernel) { this.kernel = kernel; } public ISession CreateFoo(int someParameter) { return this.kernel.Get<IFoo>( new ConstructorArgument("someParameter", someParameter)); } } 
+8
source share

I really appreciate all the other answers. They will help me solve this problem. I will most likely be accepting the Remo answer, as it corresponds to the current problem that I am really facing.

For my understanding, I would also like to receive feedback on this broader answer that I came up with.


I was not sure that Injection Dependency directly supports the mechanisms I spoke of through a constructor, property, or injection method. This is what I consider to be a “pure” DI at the moment, although I am ready for it to swing.

I thought injection dependencies meant a relatively static graph of objects. It can be loaded from a configuration file or generated using a procedure, but it cannot directly place an unrecognized execution state, for example, a user repeatedly requests new instances.

However, after thinking through some of these alternatives, I begin to think that there is a workaround that supports purity, and that maybe the purity that I described is not as important as I thought. Some of the less “clean” options still work with most containers in a mostly clean way, and it seems easy enough to add container support to clean them to the end.

Here are the workarounds that I have reviewed so far (some of them have already been mentioned).

Link to the container in custom factories, then wash your hands:

Your components can be implemented as you wish. You can use any container you need (if it supports temporary instances). You just need to live with the fact that you will enter the factories in your code and that these plants will be solved directly from the container. Who needs cleanliness when you can pragmatically?

Code example:

 public class ComponentFactory // Might inherit from an interface... { private readonly IContainer container; public ComponentFactory(IContainer container) { this.container = container; } public IComponent Create(IOtherComponent otherComponent) { return container.Get<IComponent>(otherComponent); } } 

Use the factory extension for the container:

Your components can be implemented as you wish. But your container must directly support the injection of factories into your code and automatically execute these plants so that they do not have any specific knowledge about the container.

Code example:

 // Black magic - the container implemented it for us! // But the container basically implemented our code from the previous example... public interface IComponentFactory { public IComponent Create(IOtherComponent otherComponent); } 

Use a pool of container-specific objects:

Make sure your components are stateless and allow you to combine them. The container will take care of selecting or combining objects for you. This is a more or less managed factory with a fancy implementation that you need to both distribute and free.

Pseudocode (I have not used a pool of conatiner-based objects before):

 public class SomeUI { private readonly IComponentPool componentPool; public OtherComponent(IComponentPool componentPool) { this.componentPool = componentPool; } public void DoSomethingWhenButtonPushed() { var component = componentPool.Get(); component.DoSomething(); componentPool.Release(component); } } 

The advantage of this pseudo code is that you did not need to define an interface for your factory. The downside is that you had to depend on the interface of the pool, so your container has your antennae on you. Also, I was not able to pass anything to the Get method. This probably makes sense, since objects should support instance reuse.

If real pools do not work like that, they may look identical to the factory extension container described above, only they always require the Release method along with the Create method.

Use the Flyweight template:

( Flyweight Pattern - Not sure if I defined the pattern correctly, or if I just have a weird use for it)

Introduce a stateless component that acts like a behavior for your objects or a "heavy weight" component. Maintain separate “instances” of the component by using fly state objects that you pass to the behavior component, or force them to wrap the behavior component.

This will significantly affect the architecture of your components. Your implementations must be inactive, and your state object must be designed so that it works for all possible component implementations. But it fully supports the “clean” injection model (only injection into constructors, properties, methods).

This will not work well for user interfaces. Class views usually need to be created directly, and we don’t want our flies to be a user interface class ...

 public class ComponentState { // Hopefully can be less generic than this... public Dictionary<string, object> Data { get; set; } } public interface IComponent { int DoSomething(ComponentState state); } public SomeUI { private readonly IComponent component; public OtherComponent(IComponent component) { this.component = component; } public void DoSomethingWhenButtonPushed() { var state = new ComponentState(); component.DoSomething(state); } } 

Use child containers for each new instance that the user requests:

A container works best when creating a graph of objects from a single root. Instead of trying to fight it, work with it. When the user clicks the button to create a new instance of your algorithm, create a new child container for these objects and call the global configuration code, however this must be done. Then attach the child container to the parent container.

This means that spawning code needs to know about the container at some level. Maybe wrapping it in a factory is the best way.

 public class SubComponentFactory // Might inherit from an interface... { private readonly IContainer container; public ComponentFactory(IContainer container) { this.container = container; } public IComponent Create(IOtherComponent otherComponent) { // Todo: Figure out any lifecycle issues with this. // I assume the child containers get disposed with the parent container... var childContainer = container.CreateChildContainer(); childContainer.Configure(new SubComponentConfiguration()); return childContainer.Get<SubComponent>(otherComponent); } } 

The view looks like we started. But we have a new graph of objects, so I'm not sure I can call it to use the Service Locator template. The problem with this approach is most closely related to the container. Not only is the container directly referenced, but the factory relies on the implementation detail of the container supporting child containers.

+3
source share

I always like the general answers, without delving into the special containers. You say the following:

  • You need consumers to request new copies.
  • Instances should be returned (possibly for reuse).

Using a factory is probably the best approach. The second requirement can be resolved by returning IDisposable objects. Then you can write the code as follows:

 using (var algorithm = this.algoFactory.CreateNew(type)) { // use algorithm. } 

There are several ways to do this, but you can allow the implementation of the IDisposable interface interface:

 public interface IAlgorithm : IDisposable { } 

Instead of returning the real algorithm, you can return a decorator that allows the instance to return to the pool:

 public sealed class PooledAlgorithmDecorator : IAlgorithm { private readonly IAlgorithmPool pool; private IAlgorithm real; public PooledAlgorithmDecorator(IAlgorithm real, IAlgorithmPool pool) { this.real = real; this.pool = pool; } public void Dispose() { if (this.real != null) { this.Pool.ReturnToPool(this.real); this.real = null; } } } 

Now your factory can wrap real algorithms with a decorator and return it to the consumer:

 public class PooledAlgorithmFactory : IAlgorithmFactory { private readonly IAlgorithmPool pool; public PooledAlgorithmFactory(IAlgorithmPool pool) { this.pool = pool; } public IAlgorithm CreateNew(string type) { var instance = this.pool.GetInstanceOrCreateNew(type); return new PooledAlgorithmDecorator(instance, this.pool); } } 

This, of course, is just an example. Perhaps your design will be different. Depending on the container you have chosen, you may get support for factories, a pool of objects, and what not. I think that first you need to find the right design, and the next step is to see if your container can help you with this.

+2
source share

All Articles