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

无需重新编译程序集A或B,如何解决TypeLoadException加载类型T问题

解决方案:提前加载兼容动态程序集

针对你的场景,无需重新编译A或B、无需IL重写,可通过提前加载一个与程序集B元数据完全匹配的动态程序集来提供类型T,具体实现逻辑如下:

  • 构建与A引用的程序集B完全一致的程序集标识(名称、版本、公钥令牌等,若B为强名称程序集)
  • 在动态程序集中定义类型T,确保其完全限定名、成员签名(方法、属性、字段的名称及参数/返回值类型)、访问修饰符与A依赖的T完全兼容
  • 在加载程序集A之前,将这个动态程序集加载到当前AppDomain中

当CLR加载A并解析类型T时,会发现已加载的动态程序集中存在匹配的类型,从而成功完成类型绑定,避免TypeLoadException。

代码示例

using System;
using System.Reflection;
using System.Reflection.Emit;

// 1. 构建与目标程序集B完全一致的程序集标识
var targetAssemblyName = new AssemblyName("AssemblyB");
// 若B是强名称程序集,需补充设置公钥令牌和版本:
// targetAssemblyName.SetPublicKeyToken(new byte[] { /* B的公钥令牌字节 */ });
// targetAssemblyName.Version = new Version("x.x.x.x");

// 2. 创建动态程序集和模块
var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
    targetAssemblyName, 
    AssemblyBuilderAccess.Run
);
var moduleBuilder = dynamicAssembly.DefineDynamicModule(targetAssemblyName.Name);

// 3. 定义与T完全匹配的类型
var typeBuilder = moduleBuilder.DefineType(
    "YourNamespace.T", // 必须和A引用的T的完全限定名一致
    TypeAttributes.Public | TypeAttributes.Class
);

// 添加A依赖的成员(示例:无参构造函数、空实现的公开方法)
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var methodBuilder = typeBuilder.DefineMethod(
    "DoSomething",
    MethodAttributes.Public,
    typeof(void),
    Type.EmptyTypes
);
var ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);

// 完成类型定义
Type dynamicT = typeBuilder.CreateType();

// 4. 此时加载程序集A,将自动使用动态生成的T
Assembly assemblyA = Assembly.LoadFrom(@"path/to/AssemblyA.dll");

关键注意事项

  • 动态程序集的标识必须完全匹配A引用的B:程序集名称、版本、文化、公钥令牌缺一不可,否则CLR会判定为不同程序集,无法完成匹配
  • 类型T的元数据必须与A依赖的完全兼容:包括完全限定名、成员签名、访问修饰符,否则A调用T的成员时仍会抛出异常
  • 该方案基于System.Reflection.Emit实现,支持所有主流.NET运行时(.NET Framework、.NET Core/.NET 5+),属于纯托管解决方案,无需修改原有程序集或进行IL重写

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:58:25