C# 构造函数注入对象的处理
假设我有一个类与另一个类关联。它看起来类似于以下内容:C# 构造函数注入对象的处理,c#,winforms,dependency-injection,idisposable,C#,Winforms,Dependency Injection,Idisposable,假设我有一个类与另一个类关联。它看起来类似于以下内容: public class DisposableClassOne : IDisposable { private class mDisposableClassTwo; public DisplosableClassOne(DisposableClassTwo dcTwoInjected) { mDisposableClassTwo = dcTwoInjected; } public void Di
public class DisposableClassOne : IDisposable
{
private class mDisposableClassTwo;
public DisplosableClassOne(DisposableClassTwo dcTwoInjected)
{
mDisposableClassTwo = dcTwoInjected;
}
public void Dispose()
{
// Should I dispose here? or make caller dispose of dcTwoInjected
//mDisposableClassTwo.Dispose();
}
}
我应该调用mDisposableClassTwo
的Dispose
方法,还是让调用者这样处理
using(DisposableClassTwo dcTwoInjected = new DisposableClassTwo())
using(DisposableClassOne dcOne = new DisposableClassOne(dcTwoInjected))
{
// do stuff with dcOne
}
我认为让调用方处理它是最好的方法,但是我认为通过将调用放入Dispose方法,它可以保证调用它。是否有更好的方法来处理此问题?最好不要处理任何外部引用,这些引用将由调用方自己自动处理 请参阅此线程,其中建议仅处理成员变量:
我熟悉的标准是使用一次性模式。有一个虚拟的
Dispose(bool disposing
)方法。Dispose()
方法调用Dispose(true)
,终结器调用Dispose(false)
然后,在主要处理方法中:
if (disposing)
{
// Dispose of the referenced object, as well.
}
StreamWriter和StreamReader遵循此模式。如果您明确地调用Dispose()
,它们也会处理底层流
。如果您让终结器进行清理,他们将不进行清理
或者,您可以添加一个属性:DisposeChild
,如果为true,则处理子对象,如果不是,则不处理它
我也同意瑞文的观点。几乎在所有情况下,对象都应该在实例化的同一范围内进行处理。我认为这是您在设计中必须做出的终身决定 DisposableClassOne是一次性的,因为它引用了DisposableClass2吗 以及 可处置类2的生命周期是否独立于可处置类1 对我来说,这两个问题的答案在每个课堂设计中都有所不同。StreamReader/Writer是一个很好的例子,第一个问题是“是”,第二个问题是“否”——一旦读者使用了StreamReader中的流,没有人会期望它被使用,所以读者会处理它
但是,如果DisposableClass2是其他资源——可能是一个文件引用,您依次传递给多个类来“做点什么”。在这种情况下,您不希望在准备就绪之前将其释放,而DisposableClassOne可能早已过时。如果您正在创建的类在逻辑上拥有(1)构造函数注入的资源,则它应该在内部将其释放。如果它不拥有资源,那么它应该什么也不做,并且依赖消费者来决定何时应该处置它 如果您的类拥有对非托管资源的引用,您可能还需要实现一个终结器(析构函数),因为不能保证任何人都会调用您的
Dispose
方法
通常,您希望避免调用方必须决定何时处理传递给类构造函数的对象的情况。调用者有可能过早地处置资源(或者超过必要的时间保留资源)。在某些设计中,这并不总是一件容易的事情。。。可悲的是,一次性对象模式并不总是与自身完美结合
(1) 所谓所有权,我的意思是,您的类控制它所传递的资源的生命周期,并且没有其他代码持有对它的引用。如果任何其他代码(其生命周期与您的类的生命周期无关)持有对该资源的引用并将独立使用它,则您不是该资源的所有者。要正确使用IDisposable对象,必须遵循“如果最后一个代码熄灭,请关灯”。有几个不错的场景,还有一个令人讨厌的场景:
最简单的答案是使用两个usings(),即使您随后去制作(并记录!),第二个IDisposable将处理第一个IDisposable。我使用的策略是由创建对象的人负责处理。如果没有,那么您将依赖于大量关于如何使用对象的假设