• .NET使用DotNetCorePlugins插件实现动态加载程序集的 API
  • 发布于 2个月前
  • 387 热度
    0 评论
DotNetCorePlugins 是一个 .NET 的开源插件项目,它提供了能够动态加载程序集的 API,然后把它们作为 .NET 主程序的扩展程序执行。这个库主要用到了 AssemblyLoadContext 技术, System.Runtime.Loader.AssemblyLoadContext,又名 ALC,提供了一些用于定义动态程序集加载行为的基本 API。这是 .NET Core 中我最喜欢但鲜为人知的 API 之一。

如何使用?
安装 McMaster.NETCore.Plugins NuGet 包。
dotnet add package McMaster.NETCore.Plugins
主要使用的 API 是 PluginLoader.CreateFromAssemblyFile, 它允许从文件中读取并加载程序集。
PluginLoader.CreateFromAssemblyFile(
    assemblyFile: "./plugins/MyPlugin/MyPlugin1.dll",
    sharedTypes: new [] { typeof(IPlugin), typeof(IServiceCollection), typeof(ILogger) },
    isUnloadable: true)
assemblyFile = 插件 .dll 的文件路径
sharedTypes = 加载程序的统一的类型列表
isUnloadable = 允许这个插件在将来的某个时候从内存中卸载。
定义接口
这是一个示例,我们定义了一个接口,里面包含了 GetName, 如下
public interface IPlugin
{
    string GetName();
}
对于插件,我们直接使用这个接口并进行实现,如下
internal class MyPlugin1 : IPlugin
{
    public string GetName() => "My plugin v1";
}
对于主程序,我们可以使用 PluginLoader API 来加载插件,程序需要使用查找磁盘中的插件程序集。一种方式是基于约定的,比如
plugins/
    $PluginName1/
        $PluginName1.dll
        (additional plugin files)
    $PluginName2/
        $PluginName2.dll
每个插件都发布到一个单独的目录中,这样可以避免插件之间的争用和重复的依赖问题。
以通过运行下面的命令,输出插件到文件夹中。
dotnet publish MyPlugin1.csproj --output plugins/MyPlugin1/
接下来,我们可以通过反射获取所有的插件,并进行加载, 代码如下
using McMaster.NETCore.Plugins;
var loaders = new List<PluginLoader>();
// 堆代码 duidaima.com
// create plugin loaders
var pluginsDir = Path.Combine(AppContext.BaseDirectory, "plugins");
foreach (var dir in Directory.GetDirectories(pluginsDir))
{
    var dirName = Path.GetFileName(dir);
    var pluginDll = Path.Combine(dir, dirName + ".dll");
    if (File.Exists(pluginDll))
    {
        var loader = PluginLoader.CreateFromAssemblyFile(
            pluginDll,
            sharedTypes: new [] { typeof(IPlugin) });
        loaders.Add(loader);
    }
}

// Create an instance of plugin types
foreach (var loader in loaders)
{
    foreach (var pluginType in loader
        .LoadDefaultAssembly()
        .GetTypes()
        .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract))
    { 
        IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);

        Console.WriteLine($"Created plugin instance '{plugin.GetName()}'.");
    }
}
支持 MVC 和 Razor
另外插件还支持加载 MVC 的 Controller 和 Razor Pages。通过安装下面的 Nuget 包。
dotnet add package McMaster.NETCore.Plugins.Mvc
加载程序集的方法如下:
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        var pluginFile = Path.Combine(AppContext.BaseDirectory, "plugins/MyRazorPlugin/MyRazorPlugin.dll");
        services
            .AddMvc() 
            .AddPluginFromAssemblyFile(pluginFile);
    }
}
更多插件的使用方法,作者提供了一些示例项目,可以进行参考。
https://github.com/natemcmaster/DotNetCorePlugins
用户评论