PAYATHON 2026

.NET 如何隔离两个同名但不兼容的 LLRP.dll?

数据小陈

结论

可以用不同的 AssemblyLoadContext 加载两套 SDK 和各自的 LLRP.dll。在 .NET 10 中,仅靠项目文件里的两个 <Reference> 或 SpecificVersion 设置,无法保证运行时将同名依赖分别交给对应的 SDK。要可靠隔离,应将 ThingMagic SDK 及其 LLRP 依赖放在独立加载上下文中。如果应用难以划分两套 SDK 的调用边界,拆成两个进程通常更简单。

目前的项目文件显示,应用同时引用了 OctaneSDK 和 Assemblies/LLRP.dll。不过,这些信息无法确认两份 LLRP 的完整程序集身份,也无法说明依赖在运行时如何加载。程序集身份除了文件名,还包括版本、区域性和公钥标记等信息。建议先检查两份 DLL 的程序集身份以及 SDK 的依赖关系。

方案一:用独立加载上下文加载 ThingMagic

将 ThingMagic 相关代码封装到单独的类库或插件目录,并把 ThingMagic SDK 及其所需的 LLRP.dll 放在该目录中。主程序继续在默认加载上下文中使用 OctaneSDK,ThingMagic 组件则由自定义 AssemblyLoadContext 加载。

以下示例演示如何在插件目录中查找托管依赖:

using System.Reflection;
using System.Runtime.Loader;

sealed class VendorLoadContext : AssemblyLoadContext
{
    private readonly string _directory;

    public VendorLoadContext(string directory)
    {
        _directory = Path.GetFullPath(directory);
    }

    protected override Assembly? Load(AssemblyName assemblyName)
    {
        if (assemblyName.Name is null)
            return null;

        var path = Path.Combine(_directory, assemblyName.Name + ".dll");
        if (!File.Exists(path))
            return null;

        // 避免把错误的同名文件加载进来;完整兼容性仍需检查版本等身份信息。
        var candidate = AssemblyName.GetAssemblyName(path);
        if (!string.Equals(candidate.Name, assemblyName.Name,
                StringComparison.OrdinalIgnoreCase))
            return null;

        return LoadFromAssemblyPath(path);
    }
}

创建上下文后,从中加载 ThingMagic 的入口程序集:

var context = new VendorLoadContext("plugins/ThingMagic");
var assembly = context.LoadFromAssemblyPath(
    Path.GetFullPath("plugins/ThingMagic/ThingMagicAdapter.dll"));

示例只展示了加载边界,没有包含 ThingMagic API 的调用代码。实际使用时,入口程序集及其依赖都需要位于该加载上下文可解析的位置。如果入口组件依赖 .deps.json 中的依赖解析信息,可以考虑使用 AssemblyDependencyResolver,并随插件一起部署相应文件。

ThingMagic 组件与主程序之间,尽量通过简单数据类型或双方共享的接口通信。不要把一个加载上下文中的 SDK 类型直接传给另一个上下文中的代码。即使类型或程序集显示相同,它们在运行时也可能具有不同的类型身份。具体采用反射、共享契约程序集还是进程间通信,取决于组件边界和调用需求。

方案二:拆分为两个进程

如果两套 SDK 都直接参与主程序的类型签名、回调或静态初始化,使用加载上下文隔离可能需要额外的适配代码。可以将 ThingMagic 访问放到单独的进程中,由主程序通过 IPC(例如本机套接字或命名管道)发送读取请求,并接收标签数据。两个进程各自拥有依赖加载环境,隔离边界也更清楚。

不适用的设置

  • <SpecificVersion>False</SpecificVersion> 影响项目引用的选择,不会为每个 SDK 建立独立的运行时依赖空间。
  • 给 DLL 改文件名不会改变其中记录的程序集身份,也不会自动修正 SDK 对依赖的引用。
  • .NET Framework 中常见的绑定重定向配置,不能通用地解决 net10.0 中两份同名依赖的隔离问题。

确定实现方案前,可以先检查两份 LLRP.dll 的程序集身份,并确认两个 SDK 实际引用的版本。如果它们能统一到同一份兼容程序集,统一依赖会更简单;如果不能,再采用独立加载上下文或独立进程。

备注:内容仅供参考。