在.NET中实现IDisposable模式的一部分是检查对象是否在所有方法/属性中处理,如下所示:
void SomeMethod()
{
if (Disposed)
throw new ObjectDisposedException("Object already disposed", (Exception)null);
...
}
使用这种管道代码而不是混乱代码,我想要一个轻量级工具,可以在实现IDisposable模式的所有类的后构建步骤中注入它。有什么建议吗?
答案 0 :(得分:5)
不要在Dispose()方法中编写这样的代码。不止一次地处理对象不是逻辑错误。它实际上经常发生,传递给StreamReader的FileStream是一个经典的例子。
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
using (var sr = new StreamReader(fs)) {
// etc..
}
}
fs 对象在这里被处理两次。如果有任何例外,避免这种情况会造成麻烦。
如果你实际上并没有像你的问题那样谈论“实现Dispose模式”,而只是想检查对象是否被处置的任何方法:保持KISS:
private bool CheckDisposed() {
if (this.disposed) throw new ObjectDisposedException();
}
或者只是内联写。不需要在异常消息中添加任何措辞。例外很清楚,只意味着一件事。当然,这种异常只能在调试会话和单元测试中发挥作用。向它投掷AOP武器并非不可能,但也许有点笨拙。当属性仅替换一行代码时,很难获得成功。不要在Dispose()方法中注入它:)
答案 1 :(得分:1)
PostSharp可能允许你这样做,虽然它似乎不再是免费的。
您应该能够在我认为的方法边界方面添加代码,然后将它添加到每个方法中(您可能希望排除Dispose方法本身。)
编辑仍有免费community edition
答案 2 :(得分:1)
在处理对象后,从所有成员抛出ObjectDisposedException并不总是合适的。甚至是除Dispose之外的所有成员。例如,在以模态方式显示然后处理后,访问由WinForms表单公开的属性是很常见的:
using(MyForm myForm = ...)
{
myForm.ShowDialog();
}
...
// Access myForm properties that correspond to values of controls in MyForm.
或者另一个例子:在FileStream被释放后,没有必要阻止调用者访问FileStream.Name
- 实际上FileStream类允许这样做。
因此,我只是将代码片段保存到手动粘贴到明确需要此功能的成员中:不要盲目地生成可能不合适的代码。
还有一点需要注意:IDisposable类有两大类:拥有IDisposable成员的类,以及直接拥有非托管资源的类。第一种情况是最常见的,特别是在您自己的应用程序代码中。
在第一种情况下,检查可能是多余的:如果需要,让拥有的IDisposable对象抛出ObjectDisposedException
就足够了。不访问拥有的IDisposable对象的成员不需要抛出。
在第二种情况下,您需要从可能尝试访问非托管资源的任何成员抛出ObjectDisposedException
,但不能从任何其他成员抛出。通常,您将对非托管资源的访问权限包含在少量私有成员中:这些成员可能是唯一需要抛出ObjectDisposedException
的成员。