我正在尝试使用依赖注入方法(使用Ninject)开发一个库,并且由于我的设计不正确,我可能会遇到某种混淆。总之,我的设计方法是
parent
对象有一个common
对象。parent
对象使用一些可变数量的child
个对象。child
个对象应使用与common
对象相同的parent
对象实例以下是我的问题域的简单模型。
interface IParent : IDisposable {
void Operation();
}
interface ICommon : IDisposable {
void DoCommonThing();
}
interface IChild1 {
void DoSomething();
}
interface IChild2 {
void DoAnotherThing();
}
class Parent : IParent {
private readonly ICommon _common;
public Parent(ICommon common) {
_common = common;
}
public void Dispose() {
_common.Dispose();
}
public void Operation() {
var c1 = ObjectFactory.GetInstance<IChild1>();
c1.DoSomething();
var c2 = ObjectFactory.GetInstance<IChild2>();
c2.DoAnotherThing();
// number of childs vary, do things until cn
_common.DoCommonThing();
}
}
class Common : ICommon {
private bool _isDisposed;
public void Dispose() {
_isDisposed = true;
}
public void DoCommonThing() {
if (_isDisposed)
throw new Exception("Common Object is Disposed");
}
}
class Child1 : IChild1
{
private readonly ICommon _common;
public Child1(ICommon common) {
_common = common;
}
public void DoSomething() {
// Do Something...
_common.DoCommonThing();
}
}
class Child2 : IChild2 {
private readonly ICommon _common;
public Child2(ICommon common) {
_common = common;
}
public void DoAnotherThing() {
// Do Another Thing...
_common.DoCommonThing();
}
}
所需child
个对象的数量各不相同。例如,根据c1.DoSomething
的返回值,我可能需要或可能不需要其他子对象。所以我不想通过构造函数注入它们,只需在需要时创建它们。但这种做法导致违反好莱坞原则。
如果不通过构造函数注入子对象,如何防止这种违规?
我希望child
个对象使用与common
对象相同的parent
对象实例。因此common
对象的生命周期应与其父对象相同。
如果没有为ICommon定义生命时间,则所有child
个对象都将拥有自己的common
对象实例。
如果在Thread或Request范围内定义了ICommon的生命周期,那么我就不能在同一个Thread或Request范围内使用parent
对象的不同实例。因为每个parent
对象都应使用自己的全新common
对象并进行处理。
所以我无法使用我所知道的终身范围选项解决它。我为第二个问题制作了另一个解决方案,但它使代码变得更糟。
首先,不是将ICommon
注入parent
对象,parent
对象,而是通过ObjectFactory
自我创建
class Parent : IParent {
private readonly ICommon _common;
public Parent() {
_common = ObjectFactory.GetInstance<ICommon>();
}
.....
然后,ICommon
对象不会将child
注入parent
对象,而是设置子对象的common
对象。
interface IChild {
ICommon Common { get; set; }
}
interface IChildN : IChild {
void DoNthThing();
}
abstract class ChildBase : IChild {
ICommon IChild.Common { get; set; }
}
class ChildN : IChildN {
public void DoNthThing() { }
}
class Parent : IParent {
private readonly ICommon _common;
public void Operation() {
var c1 = ObjectFactory.GetInstance<IChild1>();
c1.Common = _common;
c1.DoSomething();
var c2 = ObjectFactory.GetInstance<IChild2>();
c2.Common = _common;
c2.DoAnotherThing();
_common.DoCommonThing();
}
}
但是这个解决方案再次违反了好莱坞原则,我必须设置每个child
对象的Common属性。
parent
对象如何使用依赖注入将其common
对象分发给child
个对象? (最好是与Ninject一起)
关于我的问题,这是一个更普遍的问题:依赖注入如何正确应用于此模型?
注意:ObjectFactory.GetInstance
调用Ninject的Kernel.Get
答案 0 :(得分:3)
您需要使用CallScope
或NamedScope
。这些是Ninject.Extensions.NamedScope
包的一部分。这允许您将公共对象的范围限定为父对象,以便所有子请求都接收相同的公共对象。
关于子对象创建。如果您必须根据某些算法请求子对象,则需要使用工厂对其进行实例化。使用Ninject.Extensions.Factory
包来实现此目的。这样做了一个上下文保留get并将父上下文传递给子请求,因此允许在工厂创建的子节点中重用您的公共对象。
因此最终不需要使用自己的对象工厂。