使用Reflection(C#)检测方法是否被覆盖

And*_*rey 56 c# reflection overriding

假设我有一个基类TestBase,我定义了一个虚拟方法TestMe()

class TestBase
{
    public virtual bool TestMe() {  }
}
Run Code Online (Sandbox Code Playgroud)

现在我继承了这个类:

class Test1 : TestBase
{
    public override bool TestMe() {}
}
Run Code Online (Sandbox Code Playgroud)

现在,使用Reflection,我需要找出TestMe方法是否已在子类中重写 - 是否可能?

我需要它 - 我正在为类型"object"编写一个设计器可视化器来显示整个继承层次结构,并显示在哪个级别覆盖了哪些虚拟方法.

Rex*_*x M 64

给定类型Test1,您可以确定它是否有自己的实现声明TestMe:

typeof(Test1).GetMethod("TestMe").DeclaringType == typeof(Test1)
Run Code Online (Sandbox Code Playgroud)

如果声明来自基类型,则会评估为false.

请注意,由于这是测试声明,而不是真正的实现,如果它也是抽象的并且是抽象的,返回true ,因为它具有自己的声明.如果要排除该情况,请添加Test1TestMeTest1&& !GetMethod("TestMe").IsAbstract

  • 此解决方案尚未完成.它不包括Test1声明具有相同名称但参数不同的方法的情况.如果上面的测试评估为true,您只知道Test1有一个带有TestMe名称的方法,但您不知道它是否是一个覆盖.您还需要使用GetBaseDefinition()方法.如果此调用返回一个具有DeclaringType == typeof(TestBase)的MethodInfo对象,则只有这样您才能确定是否有覆盖. (20认同)
  • 是的,我做了,这是不正确的/非常有限的,从你的代码到一个有效的解决方案是相当多的工作.您甚至没有提到像`GetBaseDefinition()`这样的基本API,以及与方法隐藏或不同方法签名相关的问题. (3认同)
  • @Ciprian这不是一个完整的代码解决方案,只是解释在哪里找到相关的反射部分,如果关闭则拉. (2认同)
  • @CodeInChaos你看到你自己的评论吗? (2认同)

Ken*_*ett 21

正如@CiprianBortos指出的那样,接受的答案并不完整,如果您按原样使用它,将导致代码中出现令人讨厌的错误.

他的评论提供了神奇的解决方案GetBaseDefinition(),但是没有必要检查DeclaringType你是否想要进行通用IsOverride检查(我认为这是这个问题的重点),只是methodInfo.GetBaseDefinition() != methodInfo.

或者,作为扩展方法提供MethodInfo,我认为这将做到这一点:

public static class MethodInfoUtil
{
    public static bool IsOverride(this MethodInfo methodInfo)
    {
        return (methodInfo.GetBaseDefinition() != methodInfo);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于继承的方法,此实现返回true - 请参阅[NUnit test gist](https://gist.github.com/EdVinyard/5571213).`m.GetBaseDefinition().DeclaringType!= m.DeclaringType`效果更好. (4认同)
  • @AZ_ `this` 是使 `IsOverride` 方法成为静态方法的签名的一部分。 (2认同)

ESV*_*ESV 18

我无法让Ken Beckett建议的解决方案起作用.这就是我所确定的:

    public static bool IsOverride(MethodInfo m) {
        return m.GetBaseDefinition().DeclaringType != m.DeclaringType;
    }
Run Code Online (Sandbox Code Playgroud)

要点中有测试.

  • 奇迹般有效。非常感谢!只是关于获取 MethodInfo 实例的评论。我首先犯了一个错误来解决它: `typeof(SomeType).GetMethod(someFunctionName)` 使用这个 MethodInfo 实例 IsOverride 不起作用。你需要这样做: `someTypeInstance.GetType().GetMethod(someFunctionName)` 这当然是完全合乎逻辑的,但仍然有些微妙。显然,当调用 GetType() 时,对实例的引用保存在返回的 Type 对象中。 (2认同)

Mic*_*ays 6

一个简单的解决方案也适用于受保护的成员和属性如下:

var isDerived = typeof(Test1 ).GetMember("TestMe", 
               BindingFlags.NonPublic 
             | BindingFlags.Instance 
             | BindingFlags.DeclaredOnly).Length == 0;
Run Code Online (Sandbox Code Playgroud)

这是我在这里的答案的转贴,反过来又引用了这个问题.