You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET反射场景下如何创建反射接口的派生类以调用目标方法

问题说明

需要调用反射加载得到的类中的方法,方法入参为同个反射加载类库中定义的接口:

  • 被加载类库基于.NET Framework 4.6.1开发,核心结构如下:
public interface InterfaceA{
  // 接口成员定义
}

public class ClassA {
  public void MethodA( InterfaceA interfaceParam )
  {
    // 方法逻辑
  }  
}
  • 调用方可执行程序基于.NET Framework 4.8开发,已完成的核心反射逻辑如下:
// 加载目标类库
var asm = Assembly.LoadFrom( "...myAssembly.dll" );

// 查找ClassA类型以获取MethodA方法
var classAType = asm.GetExportedTypes().FirstOrDefault( t => t.Name == "ClassA" ); 
// 实例化ClassA
var instance = Activator.CreateInstance(classAType);

// 查找目标方法
var method = classAType.GetMethod( "MethodA");

// 查找目标接口
var interfaceAType = asm.GetExportedTypes().FirstOrDefault( t => t.Name == "InterfaceA" ); 

// 待解决:构造InterfaceA的实现类实例,传入完成方法调用
// method.Invoke( instance, new []{ /* 这里需要InterfaceA类型的实例 */} );

已知InterfaceA的所有成员定义,可实现完全匹配的方法、属性逻辑,但目标类库没有提供可直接实例化的InterfaceA派生类,无法直接创建符合要求的参数实例。

注意:不要尝试在主程序中手动定义同名同成员的InterfaceA再写实现类,即使两个接口的命名空间、名称、成员签名完全一致,只要加载自不同程序集,CLR就会判定为完全不同的类型,传参时会抛出类型不匹配异常。


实现方案

使用.NET Framework原生提供的System.Reflection.Emit能力,在运行时动态生成直接实现反射得到的InterfaceA类型的类,实例化后即可作为合法参数传入。
具体实现步骤:

  • 在当前应用程序域中创建动态程序集与动态模块,用于承载运行时生成的实现类
  • 在动态模块中定义公共类,添加InterfaceA作为其实现的接口类型
  • 遍历InterfaceA的所有成员(方法、属性、事件),为每个成员生成对应的IL实现代码,绑定你预先定义好的业务逻辑
  • 完成动态类型创建后,实例化该类型,即可传入MethodA完成调用

示例代码

以下为最小实现示例,假设InterfaceA包含一个无入参无返回值的方法Execute,需要的执行逻辑是打印一行文本:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

// 前面的反射加载逻辑不变,拿到interfaceAType、instance、method对象

// 1. 初始化动态生成环境
var assemblyName = new AssemblyName("DynamicImplAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicImplModule");

// 2. 定义实现类,标记实现InterfaceA
var typeBuilder = moduleBuilder.DefineType(
    "DynamicInterfaceAImplementation",
    TypeAttributes.Public | TypeAttributes.Class,
    null,
    new Type[] { interfaceAType }
);

// 3. 实现InterfaceA的所有方法(示例仅处理方法,属性、事件可按相同逻辑扩展)
var interfaceMethods = interfaceAType.GetMethods();
foreach (var methodInfo in interfaceMethods)
{
    // 定义方法,参数、返回值与接口方法完全匹配
    var methodBuilder = typeBuilder.DefineMethod(
        methodInfo.Name,
        MethodAttributes.Public | MethodAttributes.Virtual,
        methodInfo.ReturnType,
        methodInfo.GetParameters().Select(p => p.ParameterType).ToArray()
    );

    // 生成方法IL逻辑,以下示例逻辑为调用Console.WriteLine输出文本,可替换为自定义业务逻辑
    var ilGenerator = methodBuilder.GetILGenerator();
    ilGenerator.Emit(OpCodes.Ldstr, "InterfaceA方法被动态实现类调用");
    ilGenerator.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
    ilGenerator.Emit(OpCodes.Ret);

    // 将定义的方法绑定到接口对应的方法上,完成接口实现
    typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
}

// 4. 创建动态类型,生成实例
var implType = typeBuilder.CreateType();
var interfaceAInstance = Activator.CreateInstance(implType);

// 5. 完成方法调用
method.Invoke(instance, new object[] { interfaceAInstance });

如果接口包含属性,只需要额外为属性生成对应的get/set方法,逻辑和普通方法生成一致;如果需要给动态类传入自定义状态,可以在动态类中定义私有字段、构造方法,实例化时传入需要的上下文参数即可。
这种方式生成的实现类直接和反射加载得到的InterfaceA类型绑定,完全符合CLR类型校验规则,不会出现类型转换错误。


内容的提问来源于stack exchange,提问作者FFMG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:12:17