简体   繁体   中英

Ninject - binding generic types with constraints

Is it possible to set up a ninject binding to respect a generic constraint?

For example:

interface IFoo { }
interface IBar { }
interface IRepository<T> { }

class FooRepository<T> : IRepository<T> where T : IFoo { }
class BarRepository<T> : IRepository<T> where T : IBar { }

class Foo : IFoo { }
class Bar : IBar { }

class Program
{
    static void Main(string[] args)
    {
        IKernel kernel = new StandardKernel();

        // Use this binding only where T : IFoo
        kernel.Bind(typeof(IRepository<>)).To(typeof(FooRepository<>));

        // Use this one only where T : IBar
        kernel.Bind(typeof(IRepository<>)).To(typeof(BarRepository<>));

        var fooRepository = kernel.Get<IRepository<Foo>>();
        var barRepository = kernel.Get<IRepository<Bar>>();
    }
}

Calling this code as-is will produce a multiple activation paths exception:-

Error activating IRepository{Foo}: More than one matching bindings are available.

How can I set up the bindings to be conditional on the value of T? Ideally I'd like them to pick up the constraints from the target type, as I've already defined them there, but if I have to define them again in the binding that's also acceptable.

Maybe there is a cleaner solution but it definitely works with the When contextual binding method and some reflection:

// Use this binding only where T : IFoo
kernel.Bind(typeof(IRepository<>)).To(typeof(FooRepository<>))
   .When(r => typeof(IFoo).IsAssignableFrom(r.Service.GetGenericArguments()[0]));

// Use this one only where T : IBar
kernel.Bind(typeof(IRepository<>)).To(typeof(BarRepository<>))
  .When(r =>  typeof(IBar).IsAssignableFrom(r.Service.GetGenericArguments()[0]));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM