3
votes

I'm currently learning Ninject and dependency injection and in my current set-up I'm passing IKernel into places so other classes can instantiate certain classes or grab factory instances.

Currently I've got my factories bound as singletons, and passing IKernel into an object then doing _kernel.Get<ISomethingFactory>().CreateSomething() seems like it could be a bit of a code-smell and simply turning Ninject into a glorified service locator.

Also, my factories are being passed IKernel so they can resolve the bound implementation of the respective interface they create.

My questions are:

  1. Is it permissible for factories to function in this way, or should the factory simply instantiate the concrete type itself?

  2. Instead of passing IKernel all over the place, should I be favouring passing the factories / other services through the constructor?

1

1 Answers

4
votes

I prefer not to.. but that's just me.

Also, I don't roll my own factories.. I use Ninjects Factories extension. You can find it here:

https://github.com/ninject/ninject.extensions.factory

Basically, you create your bindings like normal, but then you create interfaces for factories (assuming WinForms here):

public interface IMainFormFactory {
    frmLogin CreateLoginForm();
    frmSettings CreateSettingsForm();
    IRepository<MainFormModel> CreateMainFormRepository();
}

..and bind it with the ToFactory extension:

using Ninject.Factories; // can't quite remember namespace at the moment

public class FactoryModule : NinjectModule {
    protected override void Load() {
        Bind<IMainFormFactory>().ToFactory();
    }
}

The factories extension doesn't need you to define a concrete implementation of this interface.. it already knows what to do with these objects based on bindings you've provided (and will still instantiate anything you haven't defined a binding for.. such as forms. Behind the scenes it creates a manager that implements this interface for you).

So then, you can do things like this:

private readonly IMainFormFactory _factory;

public frmMainForm(IMainFormFactory factory) {
    _factory = factory;
}

public void btnSettings_Click(object sender, EventArgs e) {
    // show the settings form..
    var settingsForm = _factory.CreateSettingsForm();
    settingsForm.ShowDialog();
}

..then in frmSettings it will inject as well:

public frmSettings(ISettingsFormFactory factory) {
    // as above except for ISettingsFactory
}

..this is how I choose to do things. Perhaps others have better ideas (I'd be interested in hearing them too!).