强烈推荐:这个.NET Core下的开源插件框架

共 5414字,需浏览 11分钟

 ·

2020-12-28 01:08


转自:xfrog
cnblogs.com/xfrog/p/13926438.html

前言


插件模式历史悠久,各种中大型软件基本上都会实现插件机制,以此支持功能扩展,从开发部署层面,插件机制也可实现功能解耦,对于并行开发、项目部署、功能定制等都有比较大的优势。


在.NET Core下,一般我们基于.NET Core扩展库进行开发,通常使用依赖注入、配置、设置(Options)等机制,如果将插件模式与依赖注入、配置、设置进行结合,将可以提供非常灵活的扩展机制。基于此,我们实现了一个开源的插件框架,本文将进行简单的介绍。


PluginFactory插件库


1、项目地址


Gitee:https://gitee.com/WuYeCai/pluginfactory


Github:https://github.com/xfrogcn/Xfrogcn.PluginFactory


2、Nuget包


Xfrogcn.PluginFactory 实现包,在主项目中引用


Xfrogcn.PluginFactory.Abstractions 抽象包,在插件项目中引用,或者你可以完全重新实现自己的插件机制


3、主要功能


  • 插件的自动载入


  • 通过插件的初始化接口可让插件控制主应用的依赖注入


  • 插件的启动及停止,此机制可与.NET Core的Hosting扩展结合,在宿主启动时自动启动插件


  • 抽象分离,你可以通过实现Xfrogcn.PluginFactory.Abstractions中的相关接口来完全实现自己的插件载入、启动等机制


  • 与.NET Core配置、设置、宿主等完美融合


  • 支持插件依赖程序集的多版本载入


主要概念


  • 插件载入器:对应IPluginLoader接口,负责从指定位置加载插件程序集


  • 插件工厂:对应IPluginFactory接口,负责插件的实例化及插件的启动和停止


  • 插件:对应IPlugin接口,所有插件需要实现此接口,实现插件的启动及停止机制


  • 可初始化插件:对应ISupportInitPlugin接口,通过此接口可以在依赖注入Provider构建之前向容器注入自定义的服务


  • 可配置插件:对应ISupportConfigPlugin接口,通过此接口可将插件配置与.NET Core的配置(Configuration)及设置(Options)机制集合


使用向导


示例项目可参考:Xfrogcn.PluginFactory.Example 


Gitee地址:https://gitee.com/WuYeCai/Xfrogcn.PluginFactory.Example


Github地址:https://github.com/xfrogcn/Xfrogcn.PluginFactory.Example


安装


在主程序项目中添加Xfrogcn.PluginFactory包


dotnet
dotnet add package Xfrogcn.PluginFactory


在插件项目中添加Xfrogcn.PluginFactory.Abstractions包


dotnet
dotnet add package Xfrogcn.PluginFactory.Abstractions


在主程序中启用


可通过以下两种方式来启用插件库,一是通过在Host层级的Use机制以及在依赖注入IServiceCollection层级的Add机制,以下分别说明:


通过IHostBuilder的UsePluginFactory方法启用插件库


var builder = Host.CreateDefaultBuilder(args);
builder.UsePluginFactory();


UsePluginFactory具有多个重载版本,详细请查看API文档

默认配置下,将使用程序运行目录下的Plugins目录作为插件程序集目录, 使用宿主配置文件作为插件配置文件(通常为appsettings.json)

你也可以通过使用带有 Assembly 或 IEnumerable 参数的版本直接传入插件所在的程序集


通过IServiceCollection的AddPluginFactory方法启用插件库


var builder = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddPluginFactory();
});


AddPluginFactory具有多个重载版本,详细请查看API文档

默认配置下,将使用程序运行目录下的Plugins目录作为插件程序集目录


注意:AddPluginFactory方法不会使用默认的配置文件作为插件配置,你需要显式地传入IConfiguration, 如果是在 ASP.NET Core 环境中,你可以在Startup类中直接获取到


编写插件


插件是实现了IPlugin接口的类,在插件库中也提供了PluginBase基类,一般从此类继承即可。标准插件具有启动和停止方法,通过IPluginFactory进行控制。


要编写插件,一般遵循以下步骤:


1、创建插件项目(.NET Core 类库),如TestPluginA


2、添加Xfrogcn.PluginFactory.Abstractions包


nuget
dotnet add package Xfrogcn.PluginFactory.Abstractions


3、创建插件类,如Plugin,从PluginBase继承


public class Plugin : PluginBase
{
public override Task StartAsync(IPluginContext context)
{
Console.WriteLine("插件A已启动");
return base.StartAsync(context);
}
public override Task StopAsync(IPluginContext context)
{
Console.WriteLine("插件A已停止");
return base.StopAsync(context);
}
}


启动或停止方法中可通过context中的ServiceProvider获取注入服务


4、通过PluginAttribute特性设置插件的元数据


[Plugin(Alias = "PluginA", Description = "测试插件")]
public class Plugin : PluginBase
{}


插件元数据以及插件载入的插件列表信息可以通过IPluginLoader.PluginList获取


插件启动


IPluginFactory本身实现了.NET Core扩展库的IHostedService机制,故如果你是在宿主环境下使用,如(ASP.NET Core),插件的启动及停止将自动跟随宿主进行

如果未使用宿主,可通过获取IPluginFactory实例调用相应方法来完成


// 手动启动
var pluginFactory = provider.GetRequiredService();
await pluginFactory.StartAsync(default);
await pluginFactory.StopAsync(default);


编写支持初始化的插件


在很多场景,我们需要在插件中控制宿主的依赖注入,如注入新的服务等,这时候我们可通过实现支持初始化的插件(ISupportInitPlugin)来实现,该接口的Init方法将在依赖注入构建之前调用,通过方法参数IPluginInitContext中的ServiceCollection可以控制宿主注入容器。


[Plugin(Alias = "PluginA", Description = "测试插件")]
public class Plugin : PluginBase, ISupportInitPlugin
{
public void Init(IPluginInitContext context)
{
// 注入服务
//context.ServiceCollection.TryAddScoped();
}
}


使用插件配置


插件支持 .NET Core 扩展库中的Options及Configuration机制,你只需要从SupportConfigPluginBase类继承实现插件即可,其中TOptions泛型为插件的配置类型。插件配置自动从宿主配置或启用插件工厂时传入的配置中获取,插件配置位于配置下的Plugins节点,该节点下以插件类名称或插件别名(通过PluginAttribute特性指定)作为键名,此键之下为插件的配置,如以下配置文件:


appsettings.json
{
"Plugins": {
"PluginA": {
"TestConfig": "Hello World"
},
}
}


扩展PluginA实现配置:


1、定义配置类,如PluginOptions


public class PluginOptions
{
public string TestConfig { get; set; }
}


2、实现插件


[Plugin(Alias = "PluginA", Description = "测试插件")]
public class Plugin : SupportConfigPluginBase, ISupportInitPlugin
{
public Plugin(IOptionsMonitor options) : base(options)
{
}
public void Init(IPluginInitContext context)
{
// 注入服务//context.ServiceCollection.TryAddScoped();
Console.WriteLine($"Init 插件配置:{Options.TestConfig}");
}
public override Task StartAsync(IPluginContext context)
{
Console.WriteLine("插件A已启动");
Console.WriteLine($"StartAsync 插件配置:{Options.TestConfig}");
return base.StartAsync(context);
}
public override Task StopAsync(IPluginContext context)
{
Console.WriteLine("插件A已停止");
return base.StopAsync(context);
}
}


注意:在插件初始化方法中也可使用注入的配置


3、跨插件配置


有些配置可能需要在多个插件中共享,此时你可通过Plugins下的_Share节点进行配置,此节点下配置将会被合并到插件配置中,可通过PluginOptions进行访问。 

appsettings.json
{
"Plugins": {
"PluginA": {
},
"_Share": {
"TestConfig": "Hello World"
}
}
}


插件化 ASP.NET Core


要让 ASP.NET Core 获取得到插件中的控制器,你只需要在插件的初始化方法Init中,向MVC注入插件程序集:


context.ServiceCollection.AddMvcCore()
.AddApplicationPart(typeof(Plugin).Assembly);



回复 【关闭】广
回复 【实战】获取20套实战源码
回复 【被删】
回复 【访客】访
回复 【小程序】学获取15套【入门+实战+赚钱】小程序源码
回复 【python】学微获取全套0基础Python知识手册
回复 【2019】获取2019 .NET 开发者峰会资料PPT
回复 【加群】加入dotnet微信交流群

再见,VIP,卧槽又来一个看片神器!


对抗流氓app开屏广告,你需要这款神器!


浏览 47
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报