C#中的IDisposable实现-是否可以对注入的IDisposable进行可选处理?
如果我有一个标准的抽象类,它允许注入IDisposable实例。但是,从这个类继承的一些类不应该像其他类一样处理注入的存储库。显而易见的解决方案是有一个构造函数:C#中的IDisposable实现-是否可以对注入的IDisposable进行可选处理?,c#,idisposable,C#,Idisposable,如果我有一个标准的抽象类,它允许注入IDisposable实例。但是,从这个类继承的一些类不应该像其他类一样处理注入的存储库。显而易见的解决方案是有一个构造函数: public abstract class WorkspaceViewModel : IDisposable { readonly bool _cascadeDisposeRepository; protected WorkspaceViewModel(IRepository repository, bool casc
public abstract class WorkspaceViewModel : IDisposable
{
readonly bool _cascadeDisposeRepository;
protected WorkspaceViewModel(IRepository repository, bool cascadeDisposeRepository=true)
{
_repository = repository;
_cascadeDisposeRepository = cascadeDisposeRepository;
}
编辑:
我也有一个构造函数
protected WorkspaceViewModel()
:this(new RepositoryA(), true){}
结束编辑
然后在
然而,我从未见过IDisposable以这种方式实现,我想知道这是否是一种不好的做法(如果是,为什么,还有什么更好的解决方案)
谢谢你的想法
编辑:
Mark的评论让我意识到,最好的实现可能是不使用无参数构造函数,强制从WorkspaceViewModel继承的任何类创建和处理自己的实例(并选择实现IDisposable),从WorkspaceViewModel的已实现接口中删除IDisposable时。由于您对非托管资源没有句柄,我建议将IDisposable全部删除 由于您的类是一个存储库,我怀疑它使用的数据库连接可能间接地在非托管资源上具有句柄-因此请记住将其包装在一个使用:
using(var myConn = new Connection(connectionString))
{
}
然后你就可以让托管代码的美妙之处去担心要销毁什么和保存什么——你甚至不需要考虑它。最后一个“使用”实现IDisposable的对象的实体,可以直接访问它,也可以将它传递给其他实体以供已知的临时使用,应在其上调用Dispose
。如果Moe
从某个其他实体传递了IDisposable
,该实体将固有地知道Moe何时处理它,那么Moe通常可以期望其他实体处理它,而不需要调用Dispose
本身。事实上,如果Moe使用了IDisposable
后,其他实体可能会使用它,则Moe不得调用Dispose
本身。如果Moe
传递了接口或基类类型的引用,则接口或基类不需要实现IDisposable
;即使传入的实例可能是实现IDisposable
的派生类型,这也不是Moe关心的问题。创建该实例的实体应该知道它是一种实现IDisposable
并处理它的类型
事情变得棘手的地方是工厂方法。如果工厂方法可能返回一个实现了IDisposable
的对象,并且该方法的调用方是唯一知道何时不再需要该对象的对象,那么该方法的返回类型本身应该实现IDisposable
。由于非泛型IEnumerator
接口没有遵循该模式,因此使用非泛型IEnumerable
接口的代码需要检查GetEnumerator()
implementsIDisposable
返回的每个对象,如果是,则对其调用Dispose
;与无条件地调用IDisposable
相比,如果它被IEnumerator继承,那么调用它的方便性和速度要低得多[即使只有99.9%的IEnumerator
实现会使用do nothingDispose
方法,调用已知接口支持的do nothing方法要比检查接口是否支持方法快]。请注意,让factory方法的返回类型实现或继承IDisposable
不会给调用方增加任何责任——这只会使调用方更容易履行他们将要承担的责任。您是否拥有非托管资源的句柄?否则,您根本不应该使用IDisposable(虽然你不会是第一个)。不,在这个抽象类中除了IRepository之外,没有其他非托管资源-我将编辑这篇文章来展示更多的代码,以及我为什么这样做
using(var myConn = new Connection(connectionString))
{
}