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

.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及以上版本提供的轻量程序集隔离机制,可加载独立的程序集副本:

  1. 部署准备:

    • 将B的输出文件(B.dll/B.exe)和它依赖的A 0.0.1版本A.Utils.dll单独放到一个目录(比如./B_Isolated),确保该目录下没有A的1.2.2版本。
  2. 自定义加载上下文:

    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;
        }
    }
    
  3. 在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实现程序集隔离:

  1. 部署准备:

    • 同样将B和A 0.0.1的文件放到单独目录(比如./B_Isolated)。
  2. 创建隔离应用域并调用:

    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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:54:52