Ninject - 结合泛型类型具有约束类型、Ninject

2023-09-03 17:44:55 作者:- 浮夸尘世丶

是否有可能建立一个ninject结合尊重一个通用的约束?

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

例如:

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>>();
    }
}

调用此code原样会产生多次激活路径例外: -

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

错误激活IRepository {}美孚:不止一个匹配的绑定可

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

我如何可以设置绑定是有条件的对T的价值?理想情况下,我想他们拿​​起约束从目标类型,因为我已经定义了他们那里,但如果我要在绑定再次定义他们,也是可以接受的。

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]));