Skip to content
bartelink edited this page Mar 28, 2013 · 3 revisions

The scenario

Imagine that you have a hand-coded factory:

public class MyFactory : IMyFactory
{
    readonly IResolutionRoot resolutionRoot;
 
    public MyFactory(IResolutionRoot resolutionRoot)
    {
        this.resolutionRoot = resolutionRoot;
    }
 
    IFoo IMyFactory.CreateFoo()
    {
        return this.resolutionRoot.Get<IFoo>();
    }
}

Now imagine that this factory gets injected into two other objects, A and B. If you are calling CreateFoo(), it has no knowledge regarding the context under which the new object is being created. Therefore you cannot apply the Contextual Binding features of Ninject in the normal manner. e.g. you can not specify that you want to "create FooA if called from A and FooB if called from B".

What Context Preservation Can Do For You

This is where the Context Preservation extension comes into play. When the ContextPreservationModule is Loaded (either explicitly or via the implicit Loading via the presence of the assembly allied to the fact that it matches the Ninject.Extensions.* pattern) into the Kernel you're using, the context gets preserved.

Using it to implement the scenario via Contextual Rules

This enables you to add contextual conditions to your Bindings and achieve the scenario laid out above as follows:

this.Bind<IFoo>().To<FooA>().When(request => request.ParentRequest.ParentRequest.Service == typeof(A));
this.Bind<IFoo>().To<FooB>().When(request => request.ParentRequest.ParentRequest.Service == typeof(B));
 
public class A
{
    readonly IMyFactory factory;
    public A(IMyFactory factory)
    {
        this.factory = factory;
    }
 
    public void Do()
    {
        var foo = this.factory.CreateFoo();
    }
}
 
public class B
{
    readonly IMyFactory factory;
    public B(IMyFactory factory)
    {
        this.factory = factory;
    }
 
    public void Do()
    {
        var foo = this.factory.CreateFoo();
    }
}

The outcome

With Context Preservation in force, A's Do will be provided with a FooA and B's Do() will be yielded a FooB instance.

Clone this wiki locally