为.Net项目添加动态库加载路径
本文分别基于.Net Framework和.Net Core的WPF应用程序为例,来说明如何为.Net项目添加自定义动态库加载路径。本文基于.Net Core创建WPF时,使用了.Net5作为目标框架。
1、.Net Framework
在基于.Net Framework的WPF项目中,直接在配置文件(App.config)中添加runtime节点即可。
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- 指定加载程序集时公共语言运行时搜索的子目录, 其中privatePath是相对于*.exe.config文件的相对路径, 多个文件夹以分号分隔。--> <probing privatePath="Libs\Lib1;Libs\Lib2"/> </assemblyBinding> </runtime>
2、.Net5
在基于.Net5的WPF项目中,使用privatePath已经不能够实现指定文件夹程序集的加载了,这大概时因为在.Net5中,程序集的加载依赖于应用程序的.deps.json文件,而privatePath指定的文件夹中的程序集不会被添加到.deps.json文件中。
基于"<probing privatePath="..." /> doesn't work in .Net 5.0",在项目文件(配置文件中应该也可以)设置动态库加载路径,然后基于AssemblyLoadContext类的Resolving事件,在应用程序查找未知类型时加载配置文件中的动态库。
(1)在.csproj文件中设置动态库路径
<ItemGroup> <RuntimeHostConfigurationOption Include="SubdirectoriesToProbe" Value="Plugins" /> </ItemGroup>
(2)在代码中实现类型动态加载
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { //加载程序集事件 AssemblyLoadContext.Default.Resolving += ResolveAssembly; base.OnStartup(e); } //加载指定位置程序集 private static Assembly ResolveAssembly(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName) { var probeSetting = AppContext.GetData("SubdirectoriesToProbe") as string; if (string.IsNullOrEmpty(probeSetting)) { return null; } foreach (var subDirectory in probeSetting.Split(';')) { var pathMaybe = Path.Combine(AppContext.BaseDirectory, subDirectory, $"{assemblyName.Name}.dll"); if (File.Exists(pathMaybe)) { return assemblyLoadContext.LoadFromAssemblyPath(pathMaybe); } } return null; } }