依赖项注入和 IDisposable 对象的生存期
本文关键字:对象 生存期 IDisposable 注入 依赖 | 更新日期: 2023-09-27 17:56:11
我正在尝试使用依赖注入方法(使用 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();
}
}
问题1
所需的child
对象数量各不相同。例如,根据返回值c1.DoSomething
我可能需要也可能不需要其他子对象。所以我不想通过构造函数注入它们,只是在需要时创建它们。但这种做法违反了好莱坞原则。
问题1
如何在不通过构造函数注入子对象的情况下防止这种冲突?
问题2
我希望child
对象与其parent
对象使用相同的common
对象实例。因此common
对象的生命周期应与其父对象相同。
如果没有为 ICommon 定义生存期,则所有对象都将
child
都有自己的common
对象实例。如果 ICommon 的生命周期是在线程或请求作用域中定义的,那么我不能在同一线程或请求作用域中使用
parent
对象的不同实例。因为每个parent
对象都应该使用自己的全新common
对象并对其进行处置。
所以我无法使用我知道的终身范围选项来解决它。我为第二个问题提供了另一个解决方案,但它使代码变得更糟。
首先,不是将ICommon
注入到对象parent
而是parent
对象通过ObjectFactory
class Parent : IParent {
private readonly ICommon _common;
public Parent() {
_common = ObjectFactory.GetInstance<ICommon>();
}
.....
然后,parent
对象集common
子对象的对象,而不是将ICommon
注入到child
对象中。
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
对象的公共属性。
问题2
对象如何使用依赖注入将其common
对象分发parent
child
对象?(最好使用宁注射)
问题3
关于我的问题,这有点笼统:依赖注入如何正确应用于此模型?
注意:ObjectFactory.GetInstance
调用 Ninject 的Kernel.Get
使用 CallScope
或 NamedScope
。这些是Ninject.Extensions.NamedScope
包的一部分。这允许您将公共对象的作用域限定为父对象,以便所有子请求都接收相同的公共对象。
关于子对象的创建。如果必须根据某些算法请求子对象,则需要使用工厂对其进行实例化。使用 Ninject.Extensions.Factory
包来实现此目的。这会执行上下文保留 get 并将父上下文传递给子请求,因此允许在工厂创建的子对象中重用您的公共对象。
因此,最终将不需要使用自己的对象工厂。