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

C#运行时无法加载旧版本DLL类型问题求助

问题根源与解决方案

核心问题

没错,新旧版本DLL共存就是导致加载失败的根本原因。当你加载旧版本DLL时,CLR会自动解析它的依赖项(比如Domain.SharedKernel.dll):

  • 如果当前应用域已经加载了该依赖的新版本,或者CLR在默认探测路径(当前应用的基目录)中找到了新版本,就会优先加载新版本。
  • 但旧版本DLL需要的是旧版本的Domain.SharedKernel.EventStreamer类型,新版本中这个类型可能已被修改、删除,或者版本号/签名不匹配,最终触发TypeLoadException。

之前尝试的独立AppDomain之所以无效,是因为没有配置正确的加载路径——新创建的AppDomain默认还是会从主应用的基目录查找依赖,依然会加载到新版本DLL。

解决步骤

1. 创建带私有路径的独立AppDomain

通过配置AppDomainSetup,将旧DLL所在文件夹设为新AppDomain的应用基目录和私有路径,确保新域只会从该路径加载所有依赖,完全隔离主域的新版本DLL。

首先定义一个跨域代理类(必须继承MarshalByRefObject,否则无法跨AppDomain传递对象):

public class LegacyTypeLoader : MarshalByRefObject
{
    public IEnumerable<Type> GetAggregateRootTypes(string legacyDir)
    {
        var dllPaths = Directory.GetFiles(legacyDir, "*.dll", SearchOption.AllDirectories);
        var allTypes = new List<Type>();
        
        foreach (var path in dllPaths)
        {
            try
            {
                var assembly = Assembly.LoadFile(path);
                allTypes.AddRange(assembly.GetTypes());
            }
            catch (ReflectionTypeLoadException ex)
            {
                // 过滤掉加载失败的类型,同时可以记录异常日志
                allTypes.AddRange(ex.Types.Where(t => t != null));
            }
        }
        
        return allTypes.Where(t => t.BaseType?.Name == "AggregateRoot");
    }
}

然后创建并使用独立AppDomain:

var legacyDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LegacyDlls");

// 配置新AppDomain的加载路径
var setup = new AppDomainSetup
{
    ApplicationBase = legacyDir,          // 将旧DLL目录设为新域的应用根目录
    PrivateBinPath = legacyDir,           // 私有路径指向旧DLL目录,确保依赖都从这里加载
    ShadowCopyFiles = "true"              // 启用影子复制,避免加载时锁定DLL文件
};

// 创建隔离的AppDomain
var legacyDomain = AppDomain.CreateDomain("LegacyIsolationDomain", null, setup);

try
{
    // 在新域中创建代理类实例,执行加载操作
    var typeLoader = (LegacyTypeLoader)legacyDomain.CreateInstanceAndUnwrap(
        Assembly.GetExecutingAssembly().FullName,
        typeof(LegacyTypeLoader).FullName
    );
    
    var aggregateRootTypes = typeLoader.GetAggregateRootTypes(legacyDir);
    // 处理获取到的类型
}
finally
{
    // 用完后卸载AppDomain,释放资源
    AppDomain.Unload(legacyDomain);
}

2. 确保旧DLL依赖完整

检查LegacyDlls文件夹,必须包含旧版本DLL的所有依赖项(包括旧版本的Domain.SharedKernel.dll),不能只复制需要扫描的DLL,否则新AppDomain依然会找不到依赖导致加载失败。

3. 额外注意事项

  • 不要直接在主AppDomain中调用新域加载的类型方法,除非这些类型也继承MarshalByRefObject或者可序列化,否则会触发跨域对象传递异常。
  • 如果旧DLL有强签名,要确保版本、公钥完全匹配,避免CLR拒绝加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:20:26