Search code examples
c#ninjectninject-extensions

Ninject.Extensions.Factory with non-generic type parameter


I know I can bind the following generic interface with ToFactory method.

public interface IFoo {}
public interface IFooFactory {
  TFoo Create<TFoo>() where TFoo : IFoo;
}

...

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

This code works as expected. However, if I want to use a non-generic variant, I get a Ninject activation exception because it searches for binding of IFoo, and so it seems that the factory extension does not recognize the Type argument.

public interface IFooFactoryWithType {
  IFoo Create(Type concreteType);
}

...

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

Am I doing something wrong, or is it not supported this way? In my current scenario I cannot use generic version because the type is coming from a runtime parameter. I could use some reflection hack with MakeGenericMethod and friends of course but I'd like to avoid that.


Solution

  • This is not supported out of the box. But you can exchange the IInstanceProvider with a custom implementation by doing:

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

    Also see the wiki for more information.

    Furthermore Ninject factory create T based on enum could be of interested to you.

    your IInstanceProvider implementation could look like that (i haven't tested whether it actually compiles, sorry):

    internal class TypeDefinedByArgumentInstanceProvider : StandardInstanceProvider
    {
        protected override Type GetType(MethodInfo methodInfo, object[] arguments)
        {
            return (Type)arguments.Single();
        }
    }
    
    kernel.Bind<IFooFactory>()
        .ToFactory(() => new TypeDefinedByArgumentInstanceProvider());