通过继承判断两个 MethodInfo 实例是否代表同一个(非虚)方法
Determine if two MethodInfo instances represent the same (non-virtual) method through inheritance
首先我举一个我知道答案的简单例子。考虑:
class Animal
{
public virtual void M() { Console.WriteLine("a"); }
}
class Giraffe : Animal
{
public override void M() { Console.WriteLine("g"); }
}
然后在某处代码:
var am = typeof(Animal).GetMethod("M");
var gm = typeof(Giraffe).GetMethod("M");
Console.WriteLine(am == gm); // False
Console.WriteLine(am == gm.GetBaseDefinition()); // True
我们看到 am
和 gm
不被认为是相等的,这是完全公平的(后者是对前者的覆盖)。但是,通过最后一行我们可以确定这两个方法是相关的;一个是另一个的"base method"。
(您甚至可以检查引用是否相等,(object)am == (object)gm.GetBaseDefinition()
,您仍然得到 True。)
现在对于这种情况我有一个问题。请考虑:
class Plant
{
public void N() /* non-virtual */ { }
}
class Tree : Plant
{
}
与:
var pn = typeof(Plant).GetMethod("N");
var tn = typeof(Tree).GetMethod("N");
Console.WriteLine(pn == tn); // False
// How can I determine that 'pn' and 'tn' are in a sense the same method?
在这种情况下,pn
和 tn
仍然被认为是不同的(并且它们的 ReflectedType
不同)。
如何测试它们实际上(通过继承)是否是相同的方法?
框架有内置方法吗?如果我必须手动解决这个问题,策略是什么?我是否必须检查两者是否具有相同的 DeclaringType
、相同的参数(类型)列表以及相同数量的类型参数?
您可以使用 DeclaringType
属性:
am.DeclaringType.Dump(); // Animal
gm.DeclaringType.Dump(); // Giraffe
pn.DeclaringType.Dump(); // Plant
tn.DeclaringType.Dump(); // Plant
或者您可以使用 MethodHandle
:
(am.MethodHandle == gm.MethodHandle).Dump(); // False
(pn.MethodHandle == tn.MethodHandle).Dump(); // True
虽然我不确定这是否完全可靠。
如果你只关心方法是否在给定类型中被实际重写,你也可以使用BindingFlags
:
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null
首先我举一个我知道答案的简单例子。考虑:
class Animal
{
public virtual void M() { Console.WriteLine("a"); }
}
class Giraffe : Animal
{
public override void M() { Console.WriteLine("g"); }
}
然后在某处代码:
var am = typeof(Animal).GetMethod("M");
var gm = typeof(Giraffe).GetMethod("M");
Console.WriteLine(am == gm); // False
Console.WriteLine(am == gm.GetBaseDefinition()); // True
我们看到 am
和 gm
不被认为是相等的,这是完全公平的(后者是对前者的覆盖)。但是,通过最后一行我们可以确定这两个方法是相关的;一个是另一个的"base method"。
(您甚至可以检查引用是否相等,(object)am == (object)gm.GetBaseDefinition()
,您仍然得到 True。)
现在对于这种情况我有一个问题。请考虑:
class Plant
{
public void N() /* non-virtual */ { }
}
class Tree : Plant
{
}
与:
var pn = typeof(Plant).GetMethod("N");
var tn = typeof(Tree).GetMethod("N");
Console.WriteLine(pn == tn); // False
// How can I determine that 'pn' and 'tn' are in a sense the same method?
在这种情况下,pn
和 tn
仍然被认为是不同的(并且它们的 ReflectedType
不同)。
如何测试它们实际上(通过继承)是否是相同的方法?
框架有内置方法吗?如果我必须手动解决这个问题,策略是什么?我是否必须检查两者是否具有相同的 DeclaringType
、相同的参数(类型)列表以及相同数量的类型参数?
您可以使用 DeclaringType
属性:
am.DeclaringType.Dump(); // Animal
gm.DeclaringType.Dump(); // Giraffe
pn.DeclaringType.Dump(); // Plant
tn.DeclaringType.Dump(); // Plant
或者您可以使用 MethodHandle
:
(am.MethodHandle == gm.MethodHandle).Dump(); // False
(pn.MethodHandle == tn.MethodHandle).Dump(); // True
虽然我不确定这是否完全可靠。
如果你只关心方法是否在给定类型中被实际重写,你也可以使用BindingFlags
:
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
typeof(Plant).GetMethod("N", flags).Dump(); // N
typeof(Tree).GetMethod("N", flags).Dump(); // null