Best you create a factory interface like this.
Best 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().AsFactory(); For 2.2 do the implementation yourself.
This implementation is part of the container configuration and 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( new ConstructorArgument("someParameter", someParameter)); } }.
So the container has to have explicit support for it, and user code must know about a factory. That's kind of how I was thinking, because I wasn't sure how you'd get new instances any other way. How is IDisposable handled with this factory extension?
Is it up to the consumer of the factory? (I kind of prefer it that way, Castle. Windsor requiring release methods felt strange to me) – Merlyn Morgan-Graham Nov 17 at 14:00 Disposing works exactly the same way as if you would call kernel.Get() (In the end that's what happens behind the scene).
If you have a scope it is disposed by Ninject at the end of the lifetime. For transient bindings you have to dispose it yourself. – Remo Gloor Nov 17 at 15:09 @Merlyn: As @Mark Seemann's excellent book tells, the reason Windsor requires the invocation of a Release method is that it tracks all created objects, including Transient ones.
This gives a much more detailed level of control than Ninject gives / opts to take / has had implemented so far. Scope/Lifetime management in Ninject is quite different and is best understood by reading the Nate Kohari Cache and Collect article. Have a look in the code to see how InRequestScope proactively manages the Releasing in cases where one wants to preempt the Cache and Collect mechanism to manage memory use – Ruben Bartelink Nov 17 at 21:17.
I always like to show general answers, without going to much into features of special containers. You say the following: You need consumers to ask for new instances. Instances must be returned (probably to be reused).
Using a factory is probably the best approach. The second requirement can be solved by returning IDisposable objects. You can then write code like this: using (var algorithm = this.algoFactory.
CreateNew(type)) { // use algorithm. } There are multiple ways of doing this, but you can let the algorithm interface implement IDisposable: public interface IAlgorithm : IDisposable { } Instead of returning the real algorithm, you can return an decorator, that allows that instance to be returned 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 the real algorithms with the decorator and return that 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 is of course just an example.
Your design will probably be different. Depending on the container you choose, you might get support for factories, object pooling and what not. I think it is important to find the correct design first and the next step is to see whether your container might be able to help you with this.
1; You've addressed this line well: "The factory design was also a little strange because I had to return my instances to the factory when I was done with them". RAII is definitely the way to handle that. Your pool is basically what the factories looked like in Windsor.
– Merlyn Morgan-Graham Nov 18 at 1:35 1 @Merlyn: Here's a reaction to your Clarification. Calling the container from within a factory class is not considered the Service Locator pattern, as long as that factory implementation is located in the composition root. See Mark Seemann's Service Locator: roles vs. mechanics.
– Steven Nov 18 at 13:11 Great stuff. I had considered letting my code know about the factory interface, and only implementing the factory as part of my "configuration" (sounds like Composition Root is the correct term). This feels like the way to go.It seems like I'm going to need to read that book :) – Merlyn Morgan-Graham Nov 18 at 13:22.
I really appreciate everyone else's answers. They're going to help me get this problem solved. I will most likely accept Remo's answer since it matches the current problem I actually face.
For my understanding I'd also like to get feedback on this broader answer I've come up with. I was not sure Dependency Injection directly supported the mechanisms I'd talked about, through constructor, property, or method injection. These are what I'd consider "pure" DI at this point - though I'm willing to be swayed.
I thought injecting dependencies meant a relatively static object graph. It could be loaded from a config file, or procedurally generated, but it couldn't directly accommodate an unknowable runtime state, like a user repeatedly requesting new instances. However after thinking through some of these alternatives I'm starting to think that there are work-arounds that support the purity, and that maybe the purity I described isn't as important as I'd thought.
Some of the less "pure" options still work with most containers in a mostly clean manner, and it seems easy enough to add support to the container to clean them up the rest of the way. Here are the work-arounds I've considered so far (a few of these were already mentioned). Reference the container in custom factories, then wash your hands: Your components can be implemented however you want.
You can use whatever container you want (as long as it supports transient instances). You just have to live with the fact that you'll be injecting factories into your code, and that those factories will resolve from the container directly. Who needs purity when you can be pragmatic?
Example code: 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(otherComponent); } } Use a container-specific factory extension: Your components can be implemented however you want.
But your container must directly support injecting factories into your code, and auto-implementing those factories so they don't have to have any specific knowledge of the container. Example code: // 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 container-specific object pool: Make sure your components are stateless, and allow them to be pooled.
The container will take care of allocating or pooling objects for you. This is more or less a managed factory with a fancy implementation, that you have to both allocate from and deallocate to. Pseudo-code (I haven't used a conatiner-based object pool 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 didn't have to define the interface for your factory. The disadvantage is that you had to depend on the pool interface, so your container has its tendrils on you.
Also I didn't get to pass in anything to the Get method. This probably makes sense because the objects have to support instance reuse. If real pools don't work like this, they might look identical to the "container-specific factory extension" example above, only they'd always require a Release method along with the Create method.
Use the Flyweight Pattern: (Flyweight Pattern - Not sure if I've identified the pattern correctly, or if I just have a weird use for it) Inject a stateless component that acts as the behavior for your objects, or the "heavy-weight" component. Support separate "instances" of the component using flyweight state objects that you pass to the behavior component, or have them wrap the behavior component. This will drastically effect the architecture of your components.
Your implementations must be stateless, and your state object must be designed in a way that it will work for all possible component implementations. But it completely supports the "pure" injection model (only injection into constructors, properties, methods). This won't work well for UIs though.
View classes usually need to be created directly, and we don't want our "flyweight" to be a UI class... public class ComponentState { // Hopefully can be less generic than this... public Dictionary 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 the user requests: The container works best when creating an object graph from a single root.
Instead of trying to fight this, work with it. When the user clicks a button to create a new instance of your algorithm, create a new child container for those objects and call into global configuration code however it needs to be done. Then attach the child container to the parent container.
This means the spawning code will need 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(otherComponent); } } Kind of looks like where we started. But we have a new object graph root, so I'm not sure I can call this out for using the Service Locator pattern.
The problem with this approach is the most tightly coupled to the container. Not only is the container directly referenced, but the factory relies on the implementation detail of the container supporting child containers.
1 Nice work. There are lots of people wandering around with the same puzzles in their heads and architectures. Hopefully @Mark Seemann will see fit to throw in a few comments on this thread at some stage - you've done a good job on enumerating your ideas and iving a flavor (if only that) of the stuff you need to consider in your child subsystem buildup – Ruben Bartelink Nov 18 at 21:30.
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.