插件模式歷史悠久,各種中大型軟體基本上都會實作插件機制,以此支持功能擴展,從開發部署層面,插件機制也可實作功能解耦,對于并行開發、專案部署、功能定制等都有比較大的優勢,
在.NET Core下,一般我們基于.NET Core擴展庫進行開發,通常使用依賴注入、配置、設定(Options)等機制,如果將插件模式與依賴注入、配置、設定進行結合,將可以提供非常靈活的擴展機制,基于此,我們實作了一個開源的插件框架,本文將進行簡單的介紹,
目錄
- 目錄
- PluginFactory插件庫
- 主要概念
- 使用向導
- 安裝
- 在主程式中啟用
- 通過IHostBuilder的UsePluginFactory方法啟用插件庫
- 通過IServiceCollection的AddPluginFactory方法啟用插件庫
- 撰寫插件
- 插件啟動
- 撰寫支持初始化的插件
- 使用插件配置
- 插件化 ASP.NET Core
PluginFactory插件庫
- 專案地址:
- Gitee
- Github
- Nuget包:
- Xfrogcn.PluginFactory 實作包,在主專案中參考
- Xfrogcn.PluginFactory.Abstractions 抽象包,在插件專案中參考,或者你可以完全重新實作自己的插件機制
- 主要功能:
- 插件的自動載入
- 通過插件的初始化介面可讓插件控制主應用的依賴注入
- 插件的啟動及停止,此機制可與.NET Core的Hosting擴展結合,在宿主啟動時自動啟動插件
- 抽象分離,你可以通過實作Xfrogcn.PluginFactory.Abstractions中的相關介面來完全實作自己的插件載入、啟動等機制
- 與.NET Core配置、設定、宿主等完美融合
- 支持插件依賴程式集的多版本載入
主要概念
- 插件載入器:對應IPluginLoader介面,負責從指定位置加載插件程式集
- 插件工廠:對應IPluginFactory介面,負責插件的實體化及插件的啟動和停止
- 插件:對應IPlugin介面,所有插件需要實作此介面,實作插件的啟動及停止機制
- 可初始化插件:對應ISupportInitPlugin介面,通過此介面可以在依賴注入Provider構建之前向容器注入自定義的服務
- 可配置插件:對應ISupportConfigPlugin介面,通過此介面可將插件配置與.NET Core的配置(Configuration)及設定(Options)機制集合
使用向導
示例專案可參考:Xfrogcn.PluginFactory.Example Gitee地址 Github地址
安裝
在主程式專案中添加Xfrogcn.PluginFactory包
```dotnet
dotnet add package Xfrogcn.PluginFactory
```
在插件專案中添加Xfrogcn.PluginFactory.Abstractions包
```dotnet
dotnet add package Xfrogcn.PluginFactory.Abstractions
```
在主程式中啟用
可通過以下兩種方式來啟用插件庫,一是通過在Host層級的Use機制以及在依賴注入IServiceCollection層級的Add機制,以下分別說明:
通過IHostBuilder的UsePluginFactory方法啟用插件庫
```c#
var builder = Host.CreateDefaultBuilder(args);
builder.UsePluginFactory();
```
UsePluginFactory具有多個多載版本,詳細請查看API檔案
默認配置下,將使用程式運行目錄下的Plugins目錄作為插件程式集目錄, 使用宿主組態檔作為插件組態檔(通常為appsettings.json)
你也可以通過使用帶有 Assembly 或 IEnumerable<Assembly> 引數的版本直接傳入插件所在的程式集
通過IServiceCollection的AddPluginFactory方法啟用插件庫
```c#
var builder = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddPluginFactory();
});
```
AddPluginFactory具有多個多載版本,詳細請查看API檔案
默認配置下,將使用程式運行目錄下的Plugins目錄作為插件程式集目錄
注意: AddPluginFactory方法不會使用默認的組態檔作為插件配置,你需要顯式地傳入IConfiguration, 如果是在 ASP.NET Core 環境中,你可以在Startup類中直接獲取到
撰寫插件
插件是實作了IPlugin介面的類,在插件庫中也提供了PluginBase基類,一般從此類繼承即可,標準插件具有啟動和停止方法,通過IPluginFactory進行控制,
要撰寫插件,一般遵循以下步驟:
-
創建插件專案(.NET Core 類別庫),如TestPluginA
-
添加Xfrogcn.PluginFactory.Abstractions包
```nuget dotnet add package Xfrogcn.PluginFactory.Abstractions ``` -
創建插件類,如Plugin,從PluginBase繼承
```c# 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獲取注入服務
-
通過PluginAttribute特性設定插件的元資料
```c# [Plugin(Alias = "PluginA", Description = "測驗插件")] public class Plugin : PluginBase { } ```插件元資料以及插件載入的插件串列資訊可以通過IPluginLoader.PluginList獲取
插件啟動
IPluginFactory本身實作了.NET Core擴展庫的IHostedService機制,故如果你是在宿主環境下使用,如(ASP.NET Core),插件的啟動及停止將自動跟隨宿主進行
如果未使用宿主,可通過獲取IPluginFactory實體呼叫相應方法來完成
```c#
// 手動啟動
var pluginFactory = provider.GetRequiredService<IPluginFactory>();
await pluginFactory.StartAsync(default);
await pluginFactory.StopAsync(default);
```
撰寫支持初始化的插件
在很多場景,我們需要在插件中控制宿主的依賴注入,如注入新的服務等,這時候我們可通過實作支持初始化的插件(ISupportInitPlugin)來實作,該介面的Init方法將在依賴注入構建之前呼叫,通過方法引數IPluginInitContext中的ServiceCollection可以控制宿主注入容器,
```c#
[Plugin(Alias = "PluginA", Description = "測驗插件")]
public class Plugin : PluginBase, ISupportInitPlugin
{
public void Init(IPluginInitContext context)
{
// 注入服務
//context.ServiceCollection.TryAddScoped<ICustomerService>();
}
}
```
使用插件配置
插件支持 .NET Core 擴展庫中的Options及Configuration機制,你只需要從SupportConfigPluginBase<TOptions>類繼承實作插件即可,其中TOptions泛型為插件的配置型別,插件配置自動從宿主配置或啟用插件工廠時傳入的配置中獲取,插件配置位于配置下的Plugins節點,該節點下以插件類名稱或插件別名(通過PluginAttribute特性指定)作為鍵名,此鍵之下為插件的配置,如以下組態檔:
```appsettings.json
{
"Plugins": {
"PluginA": {
"TestConfig": "Hello World"
},
}
}
```
擴展PluginA實作配置:
-
定義配置類,如PluginOptions
```c# public class PluginOptions { public string TestConfig { get; set; } } ``` -
實作插件
```c# [Plugin(Alias = "PluginA", Description = "測驗插件")] public class Plugin : SupportConfigPluginBase<PluginOptions>, ISupportInitPlugin { public Plugin(IOptionsMonitor<PluginOptions> options) : base(options) { } public void Init(IPluginInitContext context) { // 注入服務 //context.ServiceCollection.TryAddScoped<ICustomerService>(); 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); } ```注意:在插件初始化方法中也可使用注入的配置
-
跨插件配置
有些配置可能需要在多個插件中共享,此時你可通過Plugins下的_Share節點進行配置,此節點下配置將會被合并到插件配置中,可通過PluginOptions進行訪問,
```appsettings.json { "Plugins": { "PluginA": { }, "_Share": { "TestConfig": "Hello World" } } } ```
插件化 ASP.NET Core
要讓 ASP.NET Core 獲取得到插件中的控制器,你只需要在插件的初始化方法Init中,向MVC注入插件程式集:
```c#
context.ServiceCollection.AddMvcCore()
.AddApplicationPart(typeof(Plugin).Assembly);
```
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/203281.html
標籤:.NET技术
上一篇:大一作業求解答
