8

I have the following code

public class Something {
    [Inject]
    public Configuration config {get;set;} //singleton
    [Inject]
    public Provider<WindowHandler> windowsProvider { get; set; } //NOT singleton

    public void Search(string text) {
        WindowHandler handler = windowsProvider.Create(xxxxxx);
        //use the new handler that was created
    }
}

but it seems the Provider takes an IContext where I put xxxxxx. Shouldn't the IContext from when I bootstrapped and created Something.cs from the kernel be used. Where is the no parameter Create method on the Provider??? (I am coming from Guice land point of view where it would be coded like above).

so the question is How do I do this correctly?

thanks, Dean

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212

2 Answers2

12

It seems you are trying to use a provider as a factory in your code.

A provider in Ninject terms is a factory that is given to Ninject to create specially created objects. Therefore it gets the resolving context which can be used to create different instances depending where the instance in injected into.

public class FooProvider : Provider<IFoo>
{
    public override IFoo CreateInstance(IContext ctx)
    {
        // add here your special IFoo creation code
        return new Foo();
    }
}

kernel.Bind<IFoo>().ToProvider<FooProvider>();

What you want is a factory in your coder that creates an instance of WindowHandler. Therefore create an interface to create the instance like this:

public interface IWindowHandlerFactory
{
    WindowHandler Create();
}

Bind<IWindowHandlerFactory>().ToFactory();

Alternatively you can inject Func<WindowHandler> without adding a configuration. But this is less meaningful in my opinion.

NOTE: All this requires Ninject.Extensions.Factory available as prerelease 3.0.0-rc2 from Nuget.

See also: http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/

Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • Func is exactly what I was looking for. Is there not a way to do that in 2.0 which is the version we are on? – Dean Hiller Jan 03 '12 at 21:57
  • 1
    See http://stackoverflow.com/questions/4840157/does-ninject-support-func-auto-generated-factory/4851885#4851885 – Remo Gloor Jan 04 '12 at 00:05
1

Well, my final solution was to cheat in ninject 2.0 with the following code...

        var windowFactory = kernel.Get<IEWindowFactory>();
        var tabFactory = kernel.Get<IETabFactory>();
        windowFactory.Kernel = kernel;
        tabFactory.Kernel = kernel;

and in the bindings list I have

Bind<IEWindowFactory>().ToSelf().InSingletonScope();
Bind<IETabFactory>().ToSelf().InSingletonScope();

and after that I just start my app

var main = kernel.Get<MainForm>();
main.Start();

and of course the factories are injected where I need them in the heirarchy of that MainForm.

so I manually put the kernel when starting up and then when I bootstrap my app, naturally these factories are fields in classes with [Ninject] annotation and so they can create objects. not the cleanest until we get 3.0, but it works(and I hate the extra factory classes I have to write code for but oh well).

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212