编辑 - 新问题
好的,让我们更笼统地重新表述这个问题。
使用反射,有没有办法在运行时动态调用您可能覆盖的基类方法。您不能在编译时使用“base”关键字,因为您无法确定它是否存在。在运行时,我想列出我的祖先方法并调用祖先方法。
我尝试使用 GetMethods() 等,但它们返回的只是指向该方法的最派生实现的“指针”。不是基类的实现。
背景
我们正在使用 C# 3.0 开发一个具有相对较大的类层次结构的系统。其中一些类,在层次结构中的任何位置,都具有需要释放的资源,它们实现了IDisposable接口。
问题
现在,为了方便代码的维护和重构,我想为实现 IDisposable 的类找到一种方法,如果任何祖先也实现 IDisposable ,则“自动”调用base.Dispose(bDisposing) 。这样,如果层次结构中较高的某个类开始实现或停止实现 IDisposable,它将自动得到处理。
问题有两个方面。
- 首先,查找是否有任何祖先实现了 IDisposable。
- 其次,有条件地调用 base.Dispose(bDisposing)。
第一部分,关于实现 IDisposable 的祖先的发现,我已经能够处理。
第二部分是棘手的部分。尽管我付出了所有努力,但我还是无法从派生类中调用 base.Dispose(bDisposing)。我所有的尝试都失败了。它们要么导致编译错误,要么调用错误的 Dispose() 方法,这是最衍生的方法,因此永远循环。
主要问题是,如果没有实现它的祖先之类的东西,您实际上不能在代码中直接引用 base.Dispose() (请注意,可能还没有实现 IDisposable 的祖先,但我希望派生代码准备好何时以及如果将来发生这样的事情)。这给我们留下了反射机制,但我没有找到合适的方法。我们的代码充满了先进的反射技术,我想我没有错过任何明显的东西。
我的解决方案
我最好的办法是在注释代码中使用一些条件代码。更改 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 祖先历史的类中仍然可以正常工作。