基类上的Ninject属性注入

Gib*_*nag 7 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 { }
Run Code Online (Sandbox Code Playgroud)

Ily*_*nov 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 { }
Run Code Online (Sandbox Code Playgroud)

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

    [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());
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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


Nec*_*tem 4

为了检查具体类型,您可以在接口ParentContext.Plan.Type上使用IRequest。这应该会给您带来您所期望的行为WhenInjectedInto。例如:

When(req => req.ParentContext.Plan.Type == typeof(B))
Run Code Online (Sandbox Code Playgroud)