.NET 8 MEF插件加载原生依赖时遇DllNotFoundException问题求助
.NET 8 MEF插件架构中原生DLL加载异常解决方案
我有一个采用MEF(System.Composition)作为插件架构的.NET 8.0应用,大部分插件运行正常,但有两个插件会在运行时抛出异常。这两个插件的共同点是依赖使用runtime目录中原生DLL的库:
- 一个依赖Microsoft.Web.WebView2
- 另一个依赖使用Skia的LiveCharts2
以LiveCharts插件为例,其runtime目录结构如下:
runtimes |-- osx | `-- native | |-- libHarfBuzzSharp.dylib | `-- libSkiaSharp.dylib |-- win-arm64 | `-- native | |-- libHarfBuzzSharp.dll | `-- libSkiaSharp.dll |-- win-x64 | `-- native | |-- libHarfBuzzSharp.dll | `-- libSkiaSharp.dll `-- win-x86 `-- native |-- libHarfBuzzSharp.dll `-- libSkiaSharp.dll
WebView插件的目录结构相同,仅DLL文件不同。该runtime目录位于插件项目的构建目录中,与插件DLL同级。
目前可通过将WebView2、Skia等依赖项移入宿主应用解决问题,但这种方式扩展性差——未来任何使用原生库的插件都需要修改宿主添加对应依赖,显然不够理想。
当宿主应用未包含Skia时,LiveCharts插件会抛出以下异常:
DllNotFoundException: Unable to load DLL 'libSkiaSharp' or one of its dependencies: The specified module could not be found. (0x8007007E)
现有插件加载代码如下:
初始化MEF容器代码
private void Init(IEnumerable<Assembly> assemblies) { _pluginManager.ImportsSatisfied += OnImportsSatisfied; var configuration = new ContainerConfiguration() .WithAssemblies(assemblies); try { using (CompositionHost host = configuration.CreateContainer()) { host.SatisfyImports(_pluginManager); } } catch (ReflectionTypeLoadException ex) { Log.Error("Could not load extension pluginNames: {0}\nLoader exceptions:{1} ", ex, ex.LoaderExceptions); } catch (Exception ex) { Log.Error("Could not load extension pluginNames: {0}", ex); } }
加载插件程序集代码
private static IEnumerable<Assembly> GetAssembliesFromNames(IEnumerable<string> pluginNames, string pluginDirectory) { List<Assembly> assemblies = new(); foreach (string pluginName in pluginNames) { try { assemblies.Add(GetAssemblyForPluginByName(pluginName, pluginDirectory)); } catch (Exception ex) { Log.Error("Could not load plugin assembly {0}: {1}", pluginName, ex); } } return assemblies; } public static Assembly GetAssemblyForPluginByName(string name, string workingDirectory) { string pluginName = Path.GetFileName(name); string pluginFolderFilePath = Path.Combine(workingDirectory, pluginName); string pluginDllPath = Path.Combine(pluginFolderFilePath, pluginName + ".dll"); if (Directory.Exists(pluginFolderFilePath) && File.Exists(pluginDllPath)) { return Assembly.LoadFrom(pluginDllPath); } throw new FileNotFoundException(name); }
现寻求无需将原生依赖移入宿主即可解决该加载异常的方案。
内容的提问来源于stack exchange,提问作者PowermacFan
相关产品推荐
相关产品推荐

