如果我有一个相当标准的抽象类,它允许注入一个IDisposable实例。但是,从此类继承的某些类不应该像其他类一样处理注入的存储库。显而易见的解决方案是使用构造函数:
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){}
结束修改
然后在recomended microsoft manner
中实现Dispose方法protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_cascadeDisposeRepository) { _repository.Dispose(); }
.....
但是,我从未见过以这种方式实现IDisposable,并且想知道这是不好的做法(如果是,为什么,以及其他什么解决方案更可取)。
感谢您的想法。
修改 Mark的评论让我意识到优选的实现可能没有无参数构造函数,强制从WorkspaceViewModel继承的任何类创建和配置它们自己的实例(并选择实现IDisposable),同时从WorkspaceViewModel的已实现接口中删除IDisposable。 p>
答案 0 :(得分:1)
由于您没有非托管资源的句柄,我建议完全删除IDisposable。
由于您的类是一个存储库,我怀疑它使用的数据库连接可能间接地处理非托管资源 - 所以只需记住将其包装在一个使用中:
using(var myConn = new Connection(connectionString))
{
}
然后你可以让托管代码的美丽担心什么可以破坏和保持活着 - 你甚至不需要考虑它。
答案 1 :(得分:0)
“使用”实现IDisposable
的对象的最后一个实体,通过直接访问它或将其传递给已知持续时间临时使用的其他实体,应该调用{ {1}}就可以了。如果Dispose
从某个其他实体传递Moe
,而该实体本身就知道Moe何时完成,那么Moe通常可以期望其他实体处理它而不需要调用IDisposable
本身。实际上,在Moe完成之后,其他实体可能会使用Dispose
,然后Moe必须不调用IDisposable
本身。如果Dispose
传递了接口或基类类型的引用,则不需要接口或基类来实现Moe
;即使传入的实例可能是实现IDisposable
的派生类型,这也不是Moe的关注点。创建该实例的实体应该知道它是一个实现IDisposable
并处理它的类型。
事情变得棘手的地方是工厂方法。如果有一个实际的可能性,工厂方法可能会返回一个实现IDisposable
的对象,并且该方法的调用者将是唯一知道何时不再需要该对象的东西,那么返回类型为方法本身应该实现IDisposable
。由于非通用IDisposable
接口不遵循该模式,因此需要使用非通用IEnumerator
接口的代码来检查IEnumerable
实现GetEnumerator()
返回的每个对象如果是这样,请致电IDisposable
;这比Dispose
无条件地调用IDisposable
更不方便和慢[[1}} [即使只有99.9%的IEnumerator
实现会有无效IEnumerator
方法,调用一个接口已知支持的do-nothing方法比检查接口是否支持方法更快]。 请注意,使用工厂方法的返回类型实现或继承Dispose
不会给调用者添加任何责任 - 这只会使调用者更容易履行他们将拥有的责任