如何在.NET类的方法和属性中注入管道代码?

时间:2011-04-07 14:31:00

标签: .net aop code-injection

在.NET中实现IDisposable模式的一部分是检查对象是否在所有方法/属性中处理,如下所示:

void SomeMethod()
{
    if (Disposed)
        throw new ObjectDisposedException("Object already disposed", (Exception)null);
    ...
}

使用这种管道代码而不是混乱代码,我想要一个轻量级工具,可以在实现IDisposable模式的所有类的后构建步骤中注入它。有什么建议吗?

3 个答案:

答案 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的成员。