.NET反射如何查找参数为类库内自定义类型的重载方法
反射获取外部类库泛型参数重载方法的方案
场景说明
现有基于.NET Framework 4.6.1编写的类库,需要通过反射调用其中的方法,类库内类结构如下:
public class ClassA { } ... public class ClassB { public void MethodA(ClassA val) { // 业务逻辑 } public void MethodA(List<ClassA> list) { // 业务逻辑 } }
调用端为基于.NET Framework 4.8的可执行程序,简化后的反射代码如下(已移除参数校验、异常处理等非核心逻辑):
// 加载目标类库 var asm = Assembly.LoadFrom("...myAssembly.dll"); // 实例化ClassB var instance = asm.CreateInstance("ClassB"); // 从类库导出类型中查找ClassB类型 var type = asm.GetExportedTypes().FirstOrDefault(t => t.Name == "ClassB"); // 按方法名过滤可以查到2个MethodA重载 var methods = type.GetMethods().Where(m => m.Name == "MethodA").ToList(); // 直接传入方法名查找会抛出歧义异常,因为存在2个同名重载 var method = type.GetMethod("MethodA");
常规通过参数类型数组匹配重载的方式,在这个场景下无法直接使用:其中一个重载的参数类型为List<ClassA>,但ClassA定义在目标类库中,调用端没有直接引用该类型,无法直接编写typeof(List<ClassA>)传入参数,错误写法示例:
... var methodA = type.GetMethod("MethodA", new [] { typeof(List<ClassA>) // 此处ClassA不属于调用端程序集,代码无法编译 } );
具体实现
不需要在调用端添加对目标类库的引用,直接在运行时通过反射构造目标参数类型即可,步骤如下:
- 从已加载的目标程序集中获取
ClassA的运行时类型对象
var classAType = asm.GetExportedTypes().First(t => t.Name == "ClassA");
- 构造
List<ClassA>对应的封闭泛型类型
首先通过typeof(List<>)获取List的开放泛型类型定义,再调用MakeGenericType方法传入上一步获取的ClassA类型,就能得到运行时的List<ClassA>类型实例:
var listOfClassAType = typeof(List<>).MakeGenericType(classAType);
- 传入构造完成的参数类型数组,精确匹配目标重载
var targetMethod = type.GetMethod("MethodA", new Type[] { listOfClassAType });
拿到targetMethod后,即可正常调用Invoke方法传入对应参数执行逻辑。
注意:如果目标类、方法不是public访问级别,需要将GetExportedTypes替换为GetTypes,同时为GetMethod传入绑定标志参数,使用BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic即可匹配非公开成员。
内容的提问来源于stack exchange,提问作者FFMG
相关产品推荐
相关产品推荐

