首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将IDisposable ( Disposable模式)实现为服务(类成员)

将IDisposable ( Disposable模式)实现为服务(类成员)
EN

Stack Overflow用户
提问于 2015-09-04 21:05:18
回答 1查看 2.7K关注 0票数 1

Disposable模式是在每个类的基础上重新实现的模式。所以,我在寻找一种方法来概括它。几年前我遇到的问题是,即使您将其实现为类本身,也不能同时从Disposable实现和其他类派生对象(C#不支持多继承)。

问题是,如何使Disposable模式得以实现,从而不需要在每个实现IDisposable?的类中显式地编写它

下面是Visual为您生成的标准可处理模式(VS 2015)。

代码语言:javascript
复制
public class TestClass : IDisposable {
    #region IDisposable Support

    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing) {
        if (!disposedValue) {
            if (disposing) {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.

            disposedValue = true;
        }
    }

    // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
    // ~DisposeTest() {
    //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    //   Dispose(false);
    // }

    // This code added to correctly implement the disposable pattern.
    public void Dispose() {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        // TODO: uncomment the following line if the finalizer is overridden above.
        // GC.SuppressFinalize(this);
    }

    #endregion
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-04 21:05:18

我的实施

这就是我想出的解决方案。

代码语言:javascript
复制
public class DisposeService<T> where T : IDisposable {
    private readonly T _disposee;
    public Action<T> ManagedAction { get; set; }
    public Action<T> UnmanagedAction { get; set; }

    public DisposeService(T disposee, Action<T> managedAction = null, Action<T> unmanagedAction = null) {
        _disposee = disposee;
        ManagedAction = managedAction;
        UnmanagedAction = unmanagedAction;
    }

    private bool _isDisposed;

    public void Dispose(bool isDisposing) {
        if (_isDisposed) return;
        if (isDisposing && ManagedAction != null) {
            ManagedAction(_disposee);
        }
        var hasUnmanagedAction = UnmanagedAction != null;
        if (hasUnmanagedAction) {
            UnmanagedAction(_disposee);
        }
        _isDisposed = true;
        if (isDisposing && hasUnmanagedAction) {
            GC.SuppressFinalize(_disposee);
        }
    }
}

这个类允许您为实现DisposableService<>的类创建一个IDisposable成员。下面是一个示例,说明如何在只有托管资源的情况下使用它。

代码语言:javascript
复制
public class TestClass : IDisposable {
    protected readonly DisposeService<TestClass> DisposeService;
    private readonly SafeHandle _handle;

    public TestClass() {
        DisposeService = new DisposeService<TestClass>(this, ps => { if (_handle != null) _handle.Dispose(); });
        _handle = new SafeFileHandle(IntPtr.Zero, true);
    }

    public void Dispose() {
        DisposeService.Dispose(true);
    }
}

它是如何工作的

  • DisposeService将在对象的Dispose上运行它的Dispose。
  • DisposeService的dispose将运行您在初始化(或在派生类中更新)时提供的托管和非托管操作。
  • 如果提供了一个GC.SuppressFinalize,UnmanagedAction将自动运行。
  • 始终确保创建DisposableService<>作为构造函数的第一个操作。

因此,下面是一个在非托管资源中使用此服务的示例。

代码语言:javascript
复制
public class TestClass : IDisposable {
    protected readonly DisposeService<TestClass> DisposeService;
    private readonly SafeHandle _handle;

    public TestClass() {
        DisposeService = new DisposeService<TestClass>(this,
            ps => { if (_handle != null) _handle.Dispose(); },
            ps => { /* Free unmanaged resources here */ });
        _handle = new SafeFileHandle(IntPtr.Zero, true);
    }

    public void Dispose() {
        DisposeService.Dispose(true);
    }

    ~TestClass() {
        DisposeService.Dispose(false);
    }
}

以及从上述类生成派生类的示例。

代码语言:javascript
复制
public class TestClassDerived : TestClass, IDisposable {
    private readonly SafeHandle _derivedHandle;

    public TestClassDerived() {
        // Copy the delegate for the base's managed dispose action.
        var baseAction = DisposeService.ManagedAction;
        // Update the managed action with new disposes, while still calling the base's disposes.
        DisposeService.ManagedAction = ps => {
            if (_derivedHandle != null) {
                _derivedHandle.Dispose();
            }
            baseAction(ps);
        };
        _derivedHandle = new SafeFileHandle(IntPtr.Zero, true);
    }
}

很容易挤柠檬。保留对基委托的引用,并将其作为派生类委托的一部分进行调用。

总的来说,应该更干净,然后管理程序的区域,这是微软自2005年以来一直提供的.

编辑:,我认为在构造函数中传递的'this‘可能是个问题。但是,情况似乎并非如此:Is it a bad practice to pass "this" as an argument?只需记住在操作中放置空检查,这样就不会尝试释放空的东西。:-)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32406584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档