1
votes

I want to let Ninject resolve an instance of T based on a specific enum input value.

I have read about Ninject's factory extension, but I couldn't find any example having the factory resolve a specific class based on an enum.

Each class derives from a base class and that derived class has several, different interfaces that Ninject also has to resolve.

For example this is how the interface should look like:

public interface IProcessFactory
{
    T Create<T>(ProcessIndex processIndex) where T : BaseProcess;
}

How can this be achieved ?

2

2 Answers

3
votes

This is not supported out of the box. You can customize it by writing your own implementation of IInstanceProvider(also see ninject Wiki entry. Then configure it for your specific factory:

kernel.Bind<IFooFactory>()
      .ToFactory(() => new MyCustomInstanceProvider());

Or alternatively, if you want to change the behavior of all .ToFactory() bindings: Rebind IInstanceProvider after loading Ninject.Extensions.Factory:

kernel.Rebind<IInstanceProvider>().To<MyCustomInstanceProvider>();

However, if it's not something you need often i would consider manually writing a factory implementation @ composition root.

Anyway, in both cases you'll need to know how to create a conditional binding. Ninject calls it Contextual Binding. One method is to use Binding-Metadata:

const string EnumKey = "EnumKey";

Bind<IFoo>().To<AFoo>()
            .WithMetadata(EnumKey, MyEnum.A);

IResolutionRoot.Get<IFoo>(x => x.Get<MyEnum>(EnumKey) == MyEnum.A);

Another way would be to create a custom IParameter and use in a conditional binding:

Bind<IFoo>().To<AFoo>()
            .When(x => x.Parameters.OfType<MyParameter>().Single().Value == A);
0
votes

There are several options available to implement AbstractFactory using DI (Ninject).

After analyzing the options, I came up with the solution provided by Mark Seemann, see http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/

The Container Based Factory solution is the one I chose, because:

  • Performance: on demand DI resolve on request, no instances loaded in the constructor
  • Easy for refactor: when we want to replace the current DI framework (Ninject) to a much better performer with (almost or even better) featureset, the only place to change are the calls inside the factory and not in the NinjectModules/Composition Root.

See also at SO: Simple Injector:Factory classes that need to create classes with dependencies