I'm using the Ninject Factory Extension to inject simple object factories into my service classes.
Here is my interface and two classes that implement it:
public interface ICar
{
void Drive();
void Stop();
}
public class Mercedes : ICar
{
public void Drive()
{
Do mercedes drive stuff...
}
public void Stop()
{
Do mercedes stop stuff...
}
}
public class Ferrari : ICar
{
public void Drive()
{
Do ferrari drive stuff...
}
public void Stop()
{
Do ferrari stop stuff...
}
}
Here is my object factory to dynamically create a car at runtime:
public interface ICarFactory
{
ICar CreateCar(string carType);
}
public class CarFactory : ICarFactory
{
public ICar CreateCar(string carType)
{
ICar car;
switch (type)
{
case "mercedes":
car = new Mercedes();
break;
case "ferrari":
car = new Ferrari();
break;
}
return car;
}
}
Then use ninject factory extension "ToFactory" method to bind my car factory interface:
public class CarModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<ICarFactory>().ToFactory();
}
}
My factory gets injected into my service class as expected and can be used to create
car objects, however ninject blows up here because it cannot properly resolve ICar
to the concrete type ie. Mercedes
or Ferrari
returned by the factory CreateCar()
method.
public CarService(string carType, ICarFactory carFactory)
{
var car = carFactory.CreateCar(carType);
}
Assuming the factory pattern I'm using here is compatible with how ninject factory extension is intended to work, how do I setup the bindings for ICar -> Ferrari, ICar -> Mercedes etc. so that they may be dynamically resolved at run time with this approach?
Thanks!
There is an example of custom factory at ninject.extension.factory
wiki
First, create custom implementation of StandardInstanceProvider
to override default factory behaviour
public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(System.Reflection.MethodInfo methodInfo, object[] arguments)
{
return (string)arguments[0];
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
At CarModule
specify UseFirstArgumentAsNameInstanceProvider
(custom instance provider) for ICarFactory
factory and names for dependencies
public class CarModule : NinjectModule
{
public override void Load()
{
Bind<ICarFactory>()
.ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());
Bind<ICar>()
.To<Mercedes>()
.Named("Mercedes");
Bind<ICar>()
.To<Ferrari>()
.Named("Ferrari");
}
}
Resolve factory and dependencies
var factory = kernel.Get<ICarFactory>();
var mercedes = factory.CreateCar("Mercedes");
var ferrari = factory.CreateCar("Ferrari");
ps: here is full example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With