【发布时间】:2008-09-16 22:53:15
【问题描述】:
编辑 - 新问题
好的,让我们更笼统地重新表述这个问题。
使用反射,有没有一种方法可以在运行时动态调用您可能会覆盖的基类方法。您不能在编译时使用“base”关键字,因为您无法确定它是否存在。在运行时,我想列出我的祖先方法并调用祖先方法。
我尝试使用 GetMethods() 等,但它们返回的只是指向该方法的最派生实现的“指针”。不是基类的实现。
背景
我们正在使用 C# 3.0 开发一个具有相对较大的类层次结构的系统。其中一些类,在层次结构中的任何地方,都有需要的资源 处置,那些实现 IDisposable 接口。
问题
现在,为了方便代码的维护和重构,我想为实现 IDisposable 的类找到一种方法, 如果任何祖先也实现了 IDisposable,则“自动”调用 base.Dispose(bDisposing)。这样,如果层次结构中较高的某个类开始实施 或停止实现将自动处理的 IDisposable。
问题有两个方面。
- 首先,查找是否有任何祖先实现了 IDisposable。
- 其次,有条件地调用base.Dispose(bDisposing)。
第一部分,关于实现 IDisposable 的祖先的发现,我已经能够处理。
第二部分是棘手的部分。尽管我所有 努力,我无法从派生类调用 base.Dispose(bDisposing) 。我所有的尝试都失败了。他们要么造成 编译错误或调用了错误的 Dispose() 方法,这是最衍生的方法,因此永远循环。
主要问题是,如果没有诸如 实现它的祖先(请注意,可能还没有实现 IDisposable 的祖先,但我希望派生代码在何时以及如果这样 将来会发生一件事)。这给我们留下了 Reflection 机制,但我没有找到合适的方法。我们的代码充满了 先进的反射技术,我想我没有错过任何明显的东西。
我的解决方案
我最好的办法是在注释代码中使用一些条件代码。更改 IDisposable 层次结构会破坏构建 (如果不存在 IDisposable 祖先)或抛出异常(如果存在 IDisposable 祖先但未调用 base.Dispose)。
这是我发布的一些代码,向您展示我的 Dispose(bDisposing) 方法的样子。我将此代码放在所有 Dispose() 的末尾 整个层次结构的方法。任何新类都是从也包含此代码的模板创建的。
public class MyOtherClassBase
{
// ...
}
public class MyDerivedClass : MyOtherClassBase, ICalibrable
{
private bool m_bDisposed = false;
~MyDerivedClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool bDisposing)
{
if (!m_bDisposed) {
if (bDisposing) {
// Dispose managed resources
}
// Dispose unmanaged resources
}
m_bDisposed = true;
Type baseType = typeof(MyDerivedClass).BaseType;
if (baseType != null) {
if (baseType.GetInterface("IDisposable") != null) {
// If you have no ancestors implementing base.Dispose(...), comment
// the following line AND uncomment the throw.
//
// This way, if any of your ancestors decide one day to implement
// IDisposable you will know about it right away and proceed to
// uncomment the base.Dispose(...) in addition to commenting the throw.
//base.Dispose(bDisposing);
throw new ApplicationException("Ancestor base.Dispose(...) not called - "
+ baseType.ToString());
}
}
}
}
那么,我想问有没有办法自动/有条件地调用 base.Dispose()?
更多背景
在应用程序中还有另一种机制,所有对象都注册到一个主类。该类检查它们是否实现了 IDisposable。 如果是这样,它们将由应用程序正确处理。这样可以避免让代码使用类来处理 自己调用 Dispose() 。因此,将 IDisposable 添加到没有 IDisposable 祖先历史的类中仍然可以正常工作。
【问题讨论】:
-
不要使用 C# 终结器(即 ~MyDerivedClass()),它们是不确定的,有时可能无法运行
标签: c# reflection idisposable