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
相关产品推荐
相关产品推荐

