Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Ninject Factory

I'm trying to create a generic factory I can call to instantiate a class and its dependencies using Ninject constructor injection. It seems to work great, but its not sitting well with me, I don't know if that's because its the first time I've used generics and an IoC container, but I think my approach is flawed. Rather than explain ill just dump my simple test console app.

Farm.cs

class Farm
{
    private readonly IAnimal _animal;
    private readonly IVehicle _vehicle;

    public Farm(IAnimal animal, IVehicle vehicle)
    {
        _animal = animal;
        _vehicle = vehicle;
    }

    public void Listen()
    {
        _animal.Speak();
        _vehicle.Run();
    }
}

program.cs

class Program
{
    static void Main(string[] args)
    {
        var farm = new NinjectFactory<Farm>().GetInstance();

        farm.Listen();

        Console.Read();
    }
}

NinjectFactory.cs

class NinjectFactory<T>
{
    public T GetInstance()
    {
        var kernel = new StandardKernel(new IoCModule());

        return kernel.Get<T>();
    }
}

NinjectModule.cs

class IoCModule : NinjectModule 
{
    public override void Load()
    {
        Bind<IAnimal>().To<Dog>();
        Bind<IVehicle>().To<Tractor>();
    }
}

Any ideas/feedback would be greatly appreciated, thanks.

like image 491
Tom Riley Avatar asked Mar 25 '26 20:03

Tom Riley


1 Answers

I'm trying to create a generic factory I can call to instantiate a class and its dependencies using Ninject constructor injection

The Ninject Kernel (or any container for that matter) IS a generic factory. You are hiding that generic factory behind a generic factory. You can simply do this:

private static StandardKernel kernel;

static void Main(string[] args)
{
    Bootstrap();

    // Resolve the application's root type
    // by using the container directly.
    var farm = kernel.Get<Farm>();

    // Operate on the root type
    farm.Listen();

    Console.Read();
}

private static Kernel Bootstrap()
{
    kernel = new StandardKernel();

    kernel.Bind<IAnimal>().To<Dog>();
    kernel.Bind<IVehicle>().To<Tractor>();
    kernel.Bind<Farm>().ToSelf();
}

If your idea is to use your generic factory to hide the container from the application, this means that application code depends on that static factory. This is a big no-no. All types should be designed around constructor injection, and injecting a generic factory is the same as injecting the kernel itself into a type. This leads to code that is hard to maintain, hard to test, and hard to be verified.

like image 198
Steven Avatar answered Mar 28 '26 11:03

Steven