基类上的Ninject属性注入

时间:2012-11-03 22:18:18

标签: c# dependency-injection ninject

我正在尝试使用ninject注入属性。鉴于下面ninject模块中的两个绑定,我希望将ConcreteDependency注入B
但是,似乎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 { }

2 个答案:

答案 0 :(得分: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));
    }
}

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

答案 1 :(得分:4)

为了检查具体类型,您可以在ParentContext.Plan.Type界面上使用IRequest。这应该为您提供WhenInjectedInto所期望的行为。例如:

When(req => req.ParentContext.Plan.Type == typeof(B))