2

如果我有一个相当标准的抽象类,它允许注入 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){} 

结束编辑

然后以推荐的微软方式实现 Dispose 方法

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            if (_cascadeDisposeRepository) { _repository.Dispose(); }
            .....

但是,我从未见过 IDisposable 以这种方式实现,并且想知道这是否是不好的做法(如果是,为什么,以及哪些其他解决方案更可取)。

谢谢你的想法。

编辑: 马克的评论让我意识到最好的实现可能没有无参数构造函数,强制从 WorkspaceViewModel 继承的任何类创建和处置自己的实例(并选择实现 IDisposable),同时从 WorkspaceViewModel 的实现接口中删除 IDisposable。

4

2 回答 2

1

由于您没有非托管资源的句柄,我建议完全删除 IDisposable。

由于您的类是一个存储库,我怀疑它使用了一个数据库连接,该连接可能间接地拥有一个非托管资源的句柄 - 所以请记住将它包装在 using 中:

using(var myConn = new Connection(connectionString))
{
}

然后,您可以让托管代码的美丽担心要销毁和保持活动的内容 - 您甚至不需要考虑它。

于 2013-10-21T04:36:14.727 回答
0

最后一个实体“使用”实现的对象IDisposable,无论是通过直接访问它还是通过将其传递给其他实体以供已知持续时间的临时使用,都应该调用Dispose它。如果从某个其他实体Moe传递一个IDisposable,该实体将固有地知道 Moe 何时完成它,那么 Moe 通常可以期望其他实体处理它并且不需要调用Dispose自己。事实上,如果其他实体IDisposable在 Moe 处理完它之后可能会使用它,那么 Moe 一定不能调用Dispose自己。如果Moe传递了接口或基类类型的引用,则无需实现接口或基类IDisposable; 即使传入的实例可能是实现的派生类型IDisposable,这也不是 Moe 关心的问题。创建该实例的实体应该知道它是一种实现IDisposable和处理它的类型。

事情变得棘手的地方是工厂方法。如果工厂方法有可能返回一个实现的对象IDisposable,并且该方法的调用者将是唯一知道何时不再需要该对象的对象,那么该方法的返回类型本身应该实现IDisposable。由于非泛型IEnumerator接口不遵循该模式,因此使用非泛型IEnumerable接口的代码需要检查实现是否返回每个对象,如果是GetEnumerator()IDisposable调用Dispose它;如果IDisposable它被IEnumerator[即使只有 99.9% 的IEnumerator实现不做任何事情Dispose方法,调用已知接口支持的无操作方法比检查接口是否支持方法要快]。 请注意,实现或继承工厂方法的返回类型IDisposable不会给调用者增加任何责任——它只会让调用者更容易履行他们无论如何都将承担的责任

于 2013-10-21T16:50:44.537 回答