我正在寻找一种简单的方法来获取方法的反射信息,从类开始,一直返回到声明接口。这是简化的代码:
public interface Ix
{
void Function();
}
public class X : Ix
{
public void Function() {}
}
public class Y : X
{
}
类X的方法信息没有关于在Ix接口中声明的函数的信息。这是电话:
var info = typeof(X).GetMethod("Function");
var baseInfo = info.GetBaseDefinition()
它返回以下数据:
info.DeclaringType --> MyNamespace.X
info.ReflectedType --> MyNamespace.X
baseInfo.DeclaringType --> MyNamespace.X
baseInfo.ReflectedType --> MyNamespace.X
Y类返回相同的信息。
如何判断这个函数是在接口Ix中声明的,而不是通过所有已实现的接口和类X或Y的基类?我可能会遗漏一些简单的东西,但我无法弄清楚是什么。这可能是个错误吗?
这是.Net Core SDK版本2.1.104和Visual Studio 2017
答案 0 :(得分:1)
您似乎想要反向查找可从GetInterfaceMap获取的信息。建立这个非常简单,
public static Dictionary<MethodInfo, List<(Type, MethodInfo)>> GetReverseInterfaceMap(Type t)
{
var reverseMap = new Dictionary<MethodInfo, List<(Type, MethodInfo)>>();
var maps = t.GetInterfaces().ToDictionary(i => i, i => t.GetInterfaceMap(i));
foreach (var m in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
var list = new List<(Type, MethodInfo)>();
foreach (var (i, map) in maps)
{
for (int index = 0; index < map.TargetMethods.Length; index++)
{
var targetMethod = map.TargetMethods[index];
if (targetMethod == m)
{
list.Add((map.InterfaceType, map.InterfaceMethods[index]));
break;
}
}
}
reverseMap[m] = list;
}
return reverseMap;
}
关于界面如何工作,有几点需要注意,因为图片并不像Derived那样简单 - &gt;基地 - &gt;接口。有一个映射描述了每个接口方法调用的具体方法。此信息随时可用,因为运行时需要它来实现接口调度。然而反过来并不那么简单。一个具体方法可能是多个接口的映射。接口方法也可以是remapped by derived classes。这一切都需要考虑在内。
答案 1 :(得分:1)
这是一个扩展方法,用于检索特定Type
在声明MethodInfo
时实现的接口的Type
:
首先,获取Type
的所有接口映射的辅助方法:
public static IEnumerable<InterfaceMapping> GetAllInterfaceMaps(this Type aType) =>
aType.GetTypeInfo()
.ImplementedInterfaces
.Select(ii => aType.GetInterfaceMap(ii));
然后,使用帮助程序获取单个方法的接口的扩展方法:
public static Type[] GetInterfacesForMethod(this MethodInfo mi) =>
mi.ReflectedType
.GetAllInterfaceMaps()
.Where(im => im.TargetMethods.Any(tm => tm == mi))
.Select(im => im.InterfaceType)
.ToArray();
如果你想要类的所有方法的接口,你可以改为使用它:
public static ILookup<MethodInfo, Type> GetMethodsForInterfaces(this Type aType) =>
aType.GetAllInterfaceMaps()
.SelectMany(im => im.TargetMethods.Select(tm => new { im.TargetType, im.InterfaceType, tm }))
.ToLookup(imtm => imtm.tm, imtm => imtm.InterfaceType);
要获取与方法对应的接口声明,可以使用:
public static IEnumerable<MethodInfo> GetInterfaceDeclarationsForMethod(this MethodInfo mi) =>
mi.ReflectedType
.GetAllInterfaceMaps()
.SelectMany(map => Enumerable.Range(0, map.TargetMethods.Length)
.Where(n => map.TargetMethods[n] == mi)
.Select(n => map.InterfaceMethods[n]));