7

我正在尝试使用ninject. 鉴于ninject下面模块中的两个绑定,我希望ConcreteDependencyB.
但是,似乎WhenInjectedInto不考虑注入的类型,只考虑目标的声明类型(在这种情况下为属性)。

有没有办法实现我预期的行为?

static void Main(string[] args)
{
    var kernel = new StandardKernel(new TestModule());
    var b = kernel.Get<B>();
    var c = kernel.Get<C>();
}

class TestModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDependency>().To<EmptyDependency>();
        Bind<IDependency>().To<ConcreteDependency>().WhenInjectedInto<B>();
    }
}

abstract class A
{
    [Inject]
    public IDependency Dependency { get; set; }
}

class B : A {}

class C : A {}

interface IDependency {}

class EmptyDependency : IDependency { }

class ConcreteDependency : IDependency { }
4

2 回答 2

8

如果可能,您应该使用构造函数注入而不是属性注入。这是一种更好的技术,由 Mark Seeman 推荐,因为使对象构造所需的依赖项显式化,并且通过构造函数的对象签名更具表现力。代码应如下所示:

    abstract class A
    {
        public IDependency Dependency { get; private set; }

        public A (IDependency dependency)
        {
            Dependency = dependency;
        }

    }

    class B : A
    {
        public B (IDependency dependency)
            : base(dependency)
        {

        }
    }

    class C : A
    {
        public C (IDependency dependency)
            : base(dependency)
        {

        }
    }

    interface IDependency { }

    class EmptyDependency : IDependency { }

    class ConcreteDependency : IDependency { }

配置将与您的示例相同。以下测试通过

    [Test]
    public void TestSpecificBindingToObjectB()
    {
        var kernel = new StandardKernel(new TestModule());
        var b = kernel.Get<B>();
        var c = kernel.Get<C>();

        Assert.AreNotEqual(b.Dependency.GetType(), c.Dependency.GetType());
        Assert.AreEqual(typeof(ConcreteDependency), b.Dependency.GetType());
    }

如果您有一个具有默认实现的可选依赖项,并且您可以使用属性装饰您的类Inject,您可以从请求中提取父信息,如下所示:

class TestModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDependency>().To<EmptyDependency>();
        Bind<IDependency>().To<ConcreteDependency>().When(req =>req.ParentContext.Request.Service == typeof(B));
    }
}

然后上面给出的相同测试通过属性注入的类层次结构。

于 2012-11-04T20:50:44.070 回答
4

为了检查具体类型,您可以ParentContext.Plan.TypeIRequest界面上使用。这应该会给你你期望的行为WhenInjectedInto。例如:

When(req => req.ParentContext.Plan.Type == typeof(B))
于 2012-11-07T01:37:20.860 回答