Reputation: 6975
I think this is a relatively straightforward scenario in Ninject but I've been having difficulty finding the right terminology to search for it.
I want to do something like:
public interface IClass
{
IInner Inner { get; }
}
public class ConcreteClass : IClass
{
public ConcreteClass(IInner inner)
{
Inner = inner;
}
public IInner Inner {get; private set;}
}
public class Test
{
private BindingObject _binding {get; set;}
private override BindingTest()
{
//These two lines need some extra configuration
Kernel.Bind<IClass>().To<ConcreteClass>();
Kernel.Bind<IInner>().To<ConcreteInner>();
_binding = new BindingObject(1);
IClass class1 = Kernel.Get<IClass>();
_binding = new BindingObject(2);
IClass class2 = Kernel.Get<IClass>();
_binding = new BindingObject(1);
IClass class3 = Kernel.Get<IClass>();
//The bindings should be set up such that these asserts both pass
Assert.AreSame(class1.Inner, class3.Inner);
Assert.AreNotSame(class1.Inner, class2.Inner);
}
}
The implementation of BindingObject
doesn't matter as this is just a toy example, the idea is just that two BindingObjects
will compare equal if and only if the int
passed to their constructor is the same. Likewise, the implementations of IInner
and ConcreteInner
don't matter.
So essentially the idea is to set up the binding such that _binding
is used as a key, and every time Ninject
needs to inject a new IInner
, it will just return the existing instance if it has one bound to that particular _binding
, and create a new one if not. Is there some straightforward in-built way to do this? If not, could I get some guidance (not necessarily a full implementation) about an approach?
Upvotes: 4
Views: 1237
Reputation: 1643
Take a look at the Custom Scope .InScope()
. That is exactly what you are looking for.
You provide an instance of an object (your BindingObject
) to the scope func<>. This object is used as an reference when creating/retrieving instances in the kernel.
The Kernel will check if an instance of IInner
exists with an reference to that object; If so return instance, otherwise create new.
Example:
Kernel.Bind<IClass>().To<ConcreteClass>();
Kernel.Bind<IInner>().To<ConcreteInner>().InScope(o => { return _binding ; });
var reference1 = new object();
var reference2 = new object();
_binding = reference1;
var class1 = kernel.Get<IClass>();
_binding = reference2;
var class2 = kernel.Get<IClass>();
_binding = reference1;
var class3 = kernel.Get<IClass>();
Here class1
and class3
will have the same reference of IInner
, whereas class2
will have another reference.
More info at: http://www.ninject.org/wiki.html under Ninject -> Using Ninject -> Object Scopes. Look near the bottom. and an little article about scopes: http://bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
//Cheers
Upvotes: 3