.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 实际引用的版本。如果它们能统一到同一份兼容程序集,统一依赖会更简单;如果不能,再采用独立加载上下文或独立进程。
备注:内容仅供参考。
