sTodorov
sTodorov

Reputation: 5461

Ninject generic bindings

I am building an application using Ninject and ASP.NET MVC 3. Is it possible with Ninject to supply a generic binding within a module like this:

 Bind(typeof(IRepository<>)).To(typeof(SomeConcreteRepository<>));

EDIT: And then for a specific type , create a class that inherits from SomeConcreteRepository:

Bind(typeof(IRepository<Person>)).To(typeof(PersonConcreteRepository));

This throws an exception that multiple bindings are available. However, is there another approach to this? Are there other DI frameworks for .NET which support this behavior?

Upvotes: 0

Views: 670

Answers (3)

Adam Lenda
Adam Lenda

Reputation: 800

public class ExtendedNinjectKernal : StandardKernel
{
    public ExtendedNinjectKernal(params INinjectModule[] modules) : base(modules) { }

    public ExtendedNinjectKernal(INinjectSettings settings, params INinjectModule[] modules) : base(settings, modules) { }

    public override IEnumerable<IBinding> GetBindings(Type service)
    {
        var bindings = base.GetBindings(service);

        //If there are multiple bindings, select the one where the service does not have generic parameters
        if (bindings.Count() > 1 && bindings.Any(a => !a.Service.IsGenericTypeDefinition))
            bindings = bindings.Where(c => !c.Service.IsGenericTypeDefinition);

        return bindings;
    }
}

Upvotes: 0

sTodorov
sTodorov

Reputation: 5461

A bit of a nasty fix but for the scenario at hand it works:

public class MyKernel: StandardKernel
  {
    public MyKernel(params INinjectModule[] modules) : base(modules) { }

    public MyKernel(INinjectSettings settings, params INinjectModule[] modules) : base(settings, modules) { }

    public override IEnumerable<IBinding> GetBindings(Type service)
    {
      var bindings = base.GetBindings(service);


      if (bindings.Count() > 1)
      {
        bindings = bindings.Where(c => !c.Service.IsGenericTypeDefinition);
      }

      return bindings;
    }
  }

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038850

You don't need the second line. Simply register the open generic types:

kernel.Bind(typeof(IRepository<>)).To(typeof(SomeConcreteRepository<>));

and later fetch a specific repository like this:

var repo = kernel.Get<IRepository<Person>>();

or you can also use a provider.

Upvotes: 3

Related Questions