.NET 6 WPF插件加载:AssemblyLoadContext加载Windows专属依赖的方案
解决.NET 6 WPF插件加载Windows专属依赖DLL的问题
你遇到的核心问题是插件构建输出中同时存在通用版和Windows专属版依赖DLL,当前加载逻辑只能获取通用版。以下是两种可行的解决方案:
方案一:修改插件构建配置,将Windows专属DLL直接输出到根目录
通过指定具体的Windows运行时标识符(RID),让MSBuild自动将对应平台的依赖DLL复制到输出根目录,替换通用版。
修改插件的csproj文件,在顶级<PropertyGroup>中添加<RuntimeIdentifier>属性:
<PropertyGroup> <TargetFramework>net6.0-windows</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <Platforms>x86</Platforms> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <!-- 指定Windows x86运行时,构建时自动复制对应平台的依赖DLL到根目录 --> <RuntimeIdentifier>win-x86</RuntimeIdentifier> </PropertyGroup>
效果说明
- 重新构建插件后,
\bin\x86\Debug\net6.0-windows根目录下会直接出现511KB的Windows专属版System.Drawing.Common.dll,原通用版会被替换。 - 无需再处理
runtimes目录,保持输出结构简洁,原有加载代码无需修改即可加载到正确的依赖DLL。
方案二:通过AssemblyLoadContext的解析事件智能加载依赖
如果无法修改插件的构建配置,可以通过订阅AssemblyLoadContext的Resolving事件,在依赖加载时优先查找Windows专属的DLL路径,避免递归加载所有文件导致的同名冲突。
修改加载代码如下:
// 创建独立的插件加载上下文 var loadContext = new AssemblyLoadContext("PluginLoadContext", isCollectible: true); // 订阅依赖解析事件,优先查找Windows runtime目录下的专属DLL loadContext.Resolving += (context, assemblyName) => { // 构造Windows专属依赖的路径 var runtimeDllPath = Path.Combine( pluginBuildOutputPath, "runtimes", "win", "lib", "net6.0", $"{assemblyName.Name}.dll" ); // 优先加载Windows专属版 if (File.Exists(runtimeDllPath)) { return context.LoadFromAssemblyPath(runtimeDllPath); } // 若找不到,再尝试加载根目录的通用版 var rootDllPath = Path.Combine(pluginBuildOutputPath, $"{assemblyName.Name}.dll"); return File.Exists(rootDllPath) ? context.LoadFromAssemblyPath(rootDllPath) : null; }; // 仅加载插件的主DLL,依赖项由解析事件自动按需加载(避免加载根目录的通用版依赖) var assemblies = Directory .GetFiles(pluginBuildOutputPath, "YourPluginMain.dll") // 替换为你的插件主DLL名称 .Select(dll => loadContext.LoadFromAssemblyPath(dll)) .ToList();
关键说明
- 仅加载插件的主DLL,依赖项由
AssemblyLoadContext自动触发解析,避免主动加载所有DLL导致的同名冲突。 - 解析逻辑优先从
runtimes/win目录获取Windows专属DLL,确保加载的是正确版本。
内容的提问来源于stack exchange,提问作者cederlof
相关产品推荐
相关产品推荐

