.NET Core跨项目调用时类库版本冲突的解决方法
解决C#跨项目程序集版本隔离问题
当控制台项目C(依赖类库A 1.2.2)调用控制台项目B(依赖类库A 0.0.1)时,出现类型加载异常:"Could not load type 'A.xyz' from assembly 'A.Utils, Version=1.2.2...",原因是A 1.2.2移除了B依赖的A.xyz类型,且运行时C加载的A版本覆盖了B所需的旧版本。以下是可行的隔离解决方案:
核心思路:通过独立加载上下文隔离版本
默认程序集加载逻辑会优先使用调用方(C)的依赖版本,因此需要将B及其依赖的A 0.0.1放入独立的加载上下文,彻底和C的版本环境分隔开。
方案1:.NET Core/.NET 5+ 使用 AssemblyLoadContext
AssemblyLoadContext是.NET Core及以上版本提供的轻量程序集隔离机制,可加载独立的程序集副本:
部署准备:
- 将B的输出文件(
B.dll/B.exe)和它依赖的A 0.0.1版本A.Utils.dll单独放到一个目录(比如./B_Isolated),确保该目录下没有A的1.2.2版本。
- 将B的输出文件(
自定义加载上下文:
using System.Runtime.Loader; using System.IO; using System.Reflection; public class IsolatedAssemblyContext : AssemblyLoadContext { private readonly string _dependencyDir; public IsolatedAssemblyContext(string dependencyDirectory) : base(isCollectible: true) { _dependencyDir = dependencyDirectory; } protected override Assembly Load(AssemblyName assemblyName) { // 优先从隔离目录加载B的依赖 string assemblyPath = Path.Combine(_dependencyDir, $"{assemblyName.Name}.dll"); if (File.Exists(assemblyPath)) { return LoadFromAssemblyPath(assemblyPath); } // 系统级依赖回退到默认上下文加载 return null; } }在C中调用隔离的B:
// 替换为你的B隔离目录实际路径 string isolatedDir = Path.Combine(AppContext.BaseDirectory, "B_Isolated"); using var isolatedContext = new IsolatedAssemblyContext(isolatedDir); // 加载B的程序集 Assembly bAssembly = isolatedContext.LoadFromAssemblyPath(Path.Combine(isolatedDir, "B.dll")); // 获取要调用的类型和方法(替换为实际类名、方法名) Type targetType = bAssembly.GetType("B.YourBusinessClass"); MethodInfo targetMethod = targetType.GetMethod("ExecuteLogic"); // 创建实例并执行方法 object instance = Activator.CreateInstance(targetType); targetMethod.Invoke(instance, null); // 可选:卸载上下文释放资源 isolatedContext.Unload();
方案2:.NET Framework 使用 AppDomain
.NET Framework中可通过创建独立AppDomain实现程序集隔离:
部署准备:
- 同样将B和A 0.0.1的文件放到单独目录(比如
./B_Isolated)。
- 同样将B和A 0.0.1的文件放到单独目录(比如
创建隔离应用域并调用:
using System; // 注意:B中被调用的类必须继承 MarshalByRefObject,否则跨域调用会序列化对象而非引用 public class BusinessClass : MarshalByRefObject { public void ExecuteLogic() { // B的业务逻辑,此处会加载A 0.0.1版本 } } // 在C中的调用代码 AppDomainSetup setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, // 指定隔离目录为私有搜索路径 PrivateBinPath = "B_Isolated" }; // 创建隔离应用域 AppDomain isolatedDomain = AppDomain.CreateDomain("B_Isolated_Domain", null, setup); try { // 在隔离域中创建B的类实例 BusinessClass bInstance = (BusinessClass)isolatedDomain.CreateInstanceAndUnwrap( "B", "B.BusinessClass"); // 执行目标方法 bInstance.ExecuteLogic(); } finally { // 卸载应用域释放资源 AppDomain.Unload(isolatedDomain); }
关键注意事项
- 确保隔离目录中只有B需要的A 0.0.1版本,避免多版本共存导致加载混乱。
- 源代码生成器兼容性:B编译时已基于A 0.0.1生成对应代码,只要运行时加载正确的A版本,就能匹配生成的类型,隔离上下文可完全解决此问题。
- 跨上下文调用的对象需支持序列化或继承
MarshalByRefObject(AppDomain场景),否则会抛出序列化异常。
内容的提问来源于stack exchange,提问作者Kartikeya
相关产品推荐
相关产品推荐

