我正在尝试使用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 { }
答案 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))