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

如何在ASP.NET项目中引用同名不同文件版本的程序集

解决同程序集版本不同文件版本的依赖路由问题

问题核心

你遇到的问题在于:两个MyCommon.Assembly的程序集版本完全一致(1.2.3.4),但文件版本不同,分别被CL1、CL2引用。ASP.NET项目需要根据URL参数选择CL1或CL2,并确保它们加载对应的MyCommon.Assembly版本。由于.NET的程序集绑定机制基于程序集版本而非文件版本,codeBase标签无法同时配置同版本的两个文件,因此需要通过其他方式实现隔离加载。

可行解决方案

方案1:利用程序集加载上下文(AssemblyLoadContext)隔离加载

.NET Core/.NET 5+推荐使用AssemblyLoadContext(ALC)实现程序集的隔离加载,每个ALC可以维护独立的程序集缓存。你可以根据请求参数创建不同的ALC,分别加载对应目录的MyCommon.Assembly,再通过ALC加载CL1/CL2并执行逻辑。

示例代码

在API接口中实现加载逻辑:

using System.Reflection;
using System.Runtime.Loader;
using System.IO;
using System.Linq;

[HttpGet("process")]
public IActionResult Process([FromQuery] string library)
{
    if (string.IsNullOrEmpty(library))
        return BadRequest("请指定要使用的类库(CL1/CL2)");

    AssemblyLoadContext alc = null;
    string commonDllPath = string.Empty;
    string targetLibraryName = library switch
    {
        "CL1" => "CL1",
        "CL2" => "CL2",
        _ => null
    };

    if (targetLibraryName == null)
        return BadRequest("无效的类库名称");

    // 创建对应加载上下文
    alc = new AssemblyLoadContext($"{targetLibraryName}_Context", isCollectible: true);
    commonDllPath = Path.Combine(AppContext.BaseDirectory, library switch
    {
        "CL1" => "v1001/MyCommon.Assembly.dll",
        "CL2" => "v1002/MyCommon.Assembly.dll",
        _ => string.Empty
    });

    try
    {
        // 加载对应的MyCommon.Assembly
        _ = alc.LoadFromAssemblyPath(commonDllPath);
        // 加载目标类库(CL1/CL2)
        var libraryAssembly = alc.LoadFromAssemblyName(new AssemblyName(targetLibraryName));
        // 获取类库中处理逻辑的类型(假设存在IMyProcessor接口)
        var processorType = libraryAssembly.GetTypes().First(t => typeof(IMyProcessor).IsAssignableFrom(t));
        var processor = Activator.CreateInstance(processorType);
        // 执行处理逻辑
        var result = processorType.GetMethod("Process")?.Invoke(processor, null);
        return Ok(result);
    }
    catch (Exception ex)
    {
        return StatusCode(500, $"加载失败:{ex.Message}");
    }
    finally
    {
        alc?.Unload(); // 释放可回收的加载上下文
    }
}

方案2:订阅程序集解析事件动态路由

通过订阅AssemblyLoadContext的Resolving事件(.NET Core/.NET 5+)或AppDomain.AssemblyResolve事件(.NET Framework),在程序集解析时根据调用来源(CL1/CL2)返回对应的MyCommon.Assembly版本。

示例代码(.NET Core/.NET 5+)

在项目启动时注册解析事件:

using System.Diagnostics;
using System.Reflection;
using System.Runtime.Loader;
using System.IO;

public void ConfigureServices(IServiceCollection services)
{
    // 注册程序集解析事件
    AssemblyLoadContext.Default.Resolving += (context, assemblyName) =>
    {
        // 仅处理MyCommon.Assembly的解析请求
        if (assemblyName.Name != "MyCommon.Assembly" || assemblyName.Version != new Version("1.2.3.4"))
            return null;

        // 遍历调用栈,确定是CL1还是CL2发起的请求
        var stackTrace = new StackTrace();
        foreach (var frame in stackTrace.GetFrames())
        {
            var callingType = frame.GetMethod()?.DeclaringType;
            if (callingType == null) continue;

            var callingAssembly = callingType.Assembly;
            var assemblyVersion = callingAssembly.GetName().Version;

            if (assemblyVersion == new Version("5.0.0.1")) // CL1的程序集版本
            {
                return context.LoadFromAssemblyPath(
                    Path.Combine(AppContext.BaseDirectory, "v1001/MyCommon.Assembly.dll"));
            }
            else if (assemblyVersion == new Version("5.0.0.2")) // CL2的程序集版本
            {
                return context.LoadFromAssemblyPath(
                    Path.Combine(AppContext.BaseDirectory, "v1002/MyCommon.Assembly.dll"));
            }
        }

        return null;
    };

    // 其他服务配置...
}

关键注意事项

  • 方案1的ALC隔离更彻底,但需要将CL1/CL2以插件方式加载,不适合直接项目引用的场景;如果CL1/CL2是项目引用,方案2更适配。
  • 方案2的栈遍历存在一定性能开销,高并发场景下建议缓存调用程序集的判断结果。
  • 确保ASP项目输出目录中v1001和v1002目录下的MyCommon.Assembly.dll已正确复制(你的csproj配置已经满足这一点)。
  • 不需要修改web.config中的codeBase配置,因为动态解析会覆盖默认的绑定逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:57:56