|
在使用软件时候,某个功能有没有可能使用时才加载DLL,而且不影响正常软件的使用呢?比如像插座一样,使用的时候插上电,不用的时候可以拔出插座,强调的.NET当然可以。这种主要用于需要在运行时增加额外的操作,或者替换目前使用的功能,可以考虑使用插件式的方式开发,以便实现灵活的可拆卸动态增加功能。在.NET framework中可以使用AppDomain来实现可拆卸动态增加功能,而在.NET Core也提供了可热插拔的上下文AssemblyLoadContext。本文就讲讲.NET Core热插拔的使用。
.NET Core实现dll文件热插拔使用步骤如下:
1、新建一个公用的属性接口层
这个接口是主要记录插件类的名称,介绍和一个要实现的接口方法,也就是我们在插件中要调用的方法,这里的接口名称为ICommand,项目名称为IPlugIn。
public interface ICommand { string Name { get; } string Description { get; } string Execute(); }2、创建插件的项目
创建需要实现插件的项目,并实现第一步的接口属性和方法。项目名称为PlugIn。
public class DoPlugin : ICommand { public string Name => "PlugIn"; public string Description => "Description PlugIn"; public string Execute() { var thisv = JsonSerializer.Serialize(this); Console.WriteLine(thisv); Console.WriteLine("插件方法中逻辑展示"); return "调用插件方法执行成功"; } }在项目属性中设置ProjectReference 下的Private节点为false,表示引用的类为公共程序集,默认为true,这里必须设置为false
<ItemGroup> <ProjectReference Include=&#34;..\IPlugIn\IPlugIn.csproj&#34;> <Private>false</Private> </ProjectReference> </ItemGroup>
3、在要使用插件的项目创建PluginLoadContext上下文
public class PluginLoadContext: AssemblyLoadContext { private AssemblyDependencyResolver _resolver; public PluginLoadContext(string pluginPath, bool isCollectible) : base(isCollectible) { _resolver = new AssemblyDependencyResolver(pluginPath); } //加载依赖项 protected override Assembly Load(AssemblyName assemblyName) { string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); if (assemblyPath != null) { return LoadFromAssemblyPath(assemblyPath); } return null; } protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) { string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); if (libraryPath != null) { return LoadUnmanagedDllFromPath(libraryPath); } return IntPtr.Zero;} }该类主要负责将给定路径的dll加载到当前应用程序域,静态方法用户获取实现了插件接口的实例。AssemblyLoadContext从概念上讲,加载上下文会创建一个用于加载、解析和可能卸载一组程序集的范围。
4、调用
//复制到任意位置,最好是项目下面,最好是绝对路径stringstr=@&#34;E:\net\PlugIn\bin\Release\net6.0\Plugin.dll&#34;;string resultString = string.Empty;// 创建 PluginLoadContext对象varalc=newPluginLoadContext(str,true);//加载程序到上下文Assemblyassembly=alc.LoadFromAssemblyPath(str);if(assembly)//创建插件对象并调用foreach (Type type in assembly.GetTypes()){ if (typeof(ICommand).IsAssignableFrom(type)) { ICommand result = Activator.CreateInstance(type) as ICommand; if (result != null) { resultString = result.Execute(); break; } }}//卸载程序集上下文alc.Unload();Console.WriteLine(resultString);Console.ReadKey();输出结果:

调用成功。需要注意的是重复调用可能会出现内存溢出的问题,大家可以在读取的时候判断一下是否加载这个程序集。
5、结语
本文讲述了.NET Core中插件式开发的实现步骤,这种插件开发主要用于桌面版的程序,它的优点是可以热插拔,方便了程序升级维护和提高了用户体验度。本实例是在.NET6的基础上开发的。希望本文对您有所收获,欢迎留言或提出异议。
源码链接:
https://pan.baidu.com/s/1fIMro987msjWje_gIbC5uw?pwd=ux6g
参考:
https://learn.microsoft.com/zh-cn/dotnet/standard/assembly/unloadability
技术群:添加小编微信并备注进群
小编微信:mm1552923
公众号:dotNet编程大全
|
|