mpalmer78
mpalmer78

Reputation: 370

Bind generic Interface in Ninject

So, I have dug for quite some time to find the answer for this with no luck.

What am I doing wrong?

Ninject throws an exception with this message:

Error activating IModelRepository{User}

No matching bindings are available, and the type is not self-bindable.


Here's my code:

I have a generic Interface:

public interface IModelRepository<T> where T: IModel
{
    //interface stuff here
}


The concrete class is:

public UserRepository : IModelRepository<User>
{
    public UserRepository(IDocumentStore documentStore, string databaseName)
    {
        //constructor code here
    }
}


Ninject module Load():

public override void Load()
{
    string databaseName = Properties.Settings.Default.DefaultDatabaseName;

    Bind<IModelRepository<User>>()
        .To<UserRepository>()
        .WithConstructorArgument("documentStore", Kernel.Get<IDocumentStore>())
        .WithConstructorArgument("databaseName", databaseName);
}


Ninject instantiation (this is where the exception occurs):

Kernel = new Ninject.StandardKernel(new DIModules.ModelRepositoryModule()
                                   ,new DIModules.DocumentStoreModule());

Here's the full stack trace:

at Ninject.KernelBase.Resolve(IRequest request) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 359
at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot root, Type service, Func`2 constraint, IEnumerable`1 parameters, Boolean isOptional, Boolean isUnique) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 263
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 37
at xl.view.DIModules.DataStoreModule.Load() in c:\Users\Michael\Google Drive\Projects\Windows\xl\xl.view\DIModules\DataStoreModule.cs:line 18
at Ninject.Modules.NinjectModule.OnLoad(IKernel kernel) in c:\Projects\Ninject\ninject\src\Ninject\Modules\NinjectModule.cs:line 85
at Ninject.KernelBase.Load(IEnumerable`1 m) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 217
at Ninject.KernelBase..ctor(IComponentContainer components, INinjectSettings settings, INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 100
at Ninject.KernelBase..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 57
at Ninject.StandardKernel..ctor(INinjectModule[] modules) in c:\Projects\Ninject\ninject\src\Ninject\StandardKernel.cs:line 46
at xl.view.Program.InitializeApplication() in c:\Projects\Windows\xl\xl.view\Program.cs:line 53
at xl.view.Program.Main() in c:\Windows\xl\xl.view\Program.cs:line 28

Upvotes: 2

Views: 1520

Answers (2)

Ruben Bartelink
Ruben Bartelink

Reputation: 61893

 .WithConstructorArgument("documentStore", Kernel.Get<IDocumentStore>())

You might want to change that to ctx=> Kernel.Get<IDocumentStore>(). The way you're calling it, you're creating objects during the module Load() - this should not be the casse - Moduel Load() methods should only Bind() stuff.

Also, don't have a dev env to hand but pretty sure there should be a way to let default provisioning take care of binding that ctor param to whatever DI would resolve.

(If none of the above makes sense, you'll definitely need to give a more complete stacktrace than you have)

Upvotes: 1

Akim
Akim

Reputation: 8689

Try to change order of modules, seems order is important, because IModelRepository<User> does not know about IModel and User before you bind them:

Kernel = new Ninject.StandardKernel(
    new DIModules.DocumentStoreModule(),
    new DIModules.ModelRepositoryModule());

This works well for me, and here is full sample: http://pastebin.com/2TjBqAwc

Upvotes: 1

Related Questions