Skip to content
Scott Xu edited this page Apr 7, 2014 · 9 revisions

The recommended way to add factories is to define an interface containing one (or several) methods to create the required dependencies as illustrated by:-

public class Foo
{
    readonly IBarFactory barFactory;

    public Foo(IBarFactory barFactory)
    {
        this.barFactory = barFactory;
    }
 
    public void Do()
    {
        var bar = this.barFactory.CreateBar();
        ...
    }
}
 
public interface IBarFactory
{
    Bar CreateBar();
}

This interface is declared near to the class that is using it (i.e., it doesn't have to go into a common Assembly unless you have other good reasons to do so). In the binding configuration it can now be bound using the ToFactory() Kernel extension method within the extension Assembly. This tells Ninject that it is to automatically implement a factory type to fulfill the specified interface and inject an instance of this factory into any object instance that requests an instance of the factory interface as it is being activated. In the case of our preceding example, the Binding statement looks like this:-

kernel.Bind<IBarFactory>().ToFactory();

Sometimes it is necessary to supply some arguments to parameters of the type being created. This can be achieved simply by adding the necessary parameters to the method declaration on the interface. The extension uses the convention that the parameter names in the method declaration should match the types and names used on the constructor of the type the factory is to resolve. The order of the parameters in the factory method and the constructor of the type being resolved do not have to match.

public class Foo
{
    readonly IBarFactory barFactory;

    public Foo(IBarFactory barFactory)
    {
        this.barFactory = barFactory;
    }
 
    public void Do(int x, int y)
    {
        var bar = this.barFactory.CreateBar(x, y);
        ...
    }
}
 
public interface IBarFactory
{
    Bar CreateBar(int x, int y);
}
 
public class Bar
{
    public Bar(int y, int x)
    {
    }
}
 
foo.Do(1, 2); // Creates a Bar instance with argument values x = 1, y = 2

Behind the scenes, Ninject will create a dynamic proxy that implements the specified factory interface and set up interceptions to handle all methods so that the proxy behaves like the following implementation of the factory interface:

public class BarFactory : IBarFactory
{
    readonly IResolutionRoot resolutionRoot;

    public BarFactory(IResolutionRoot resolutionRoot)
    {
        this.resolutionRoot = resolutionRoot;
    }
 
    Bar IBarFactory.CreateBar(int y, int x)
    {
        return this.resolutionRoot.Get<Bar>(
            new ConstructorArgument("y", y),
            new ConstructorArgument("x", x));
    }
}

Note that IBarFactory is not restricted to just having a single method on the interface. If desired, one can create an interface that offers myriad ways of resolving instances of Bar by simply adding more factory method declarations to the interface as desired. Each such method will automatically get generated as needed without requiring anything other than a the single Bind<T>().ToFactory() registration for the factory interface type.

Also note that there is a naming convention used by the extension. Any method in the factory interface that begins GetXxx will be interpreted as a request for a Binding Named 'Xxx' rather than a normal resolution.