1. 程式人生 > >一個.NET Core下的開源外掛框架

一個.NET Core下的開源外掛框架

    外掛模式歷史悠久,各種中大型軟體基本上都會實現外掛機制,以此支援功能擴充套件,從開發部署層面,外掛機制也可實現功能解耦,對於並行開發、專案部署、功能定製等都有比較大的優勢。     在.NET Core下,一般我們基於.NET Core擴充套件庫進行開發,通常使用依賴注入、配置、設定(Options)等機制,如果將外掛模式與依賴注入、配置、設定進行結合,將可以提供非常靈活的擴充套件機制。基於此,我們實現了一個開源的外掛框架,本文將進行簡單的介紹。 # 目錄 - [目錄](#目錄) - [PluginFactory外掛庫](#pluginfactory外掛庫) - [主要概念](#主要概念) - [使用嚮導](#使用嚮導) - [安裝](#安裝) - [在主程式中啟用](#在主程式中啟用) - [通過IHostBuilder的UsePluginFactory方法啟用外掛庫](#通過ihostbuilder的usepluginfactory方法啟用外掛庫) - [通過IServiceCollection的AddPluginFactory方法啟用外掛庫](#通過iservicecollection的addpluginfactory方法啟用外掛庫) - [編寫外掛](#編寫外掛) - [外掛啟動](#外掛啟動) - [編寫支援初始化的外掛](#編寫支援初始化的外掛) - [使用外掛配置](#使用外掛配置) - [外掛化 ASP.NET Core](#外掛化-aspnet-core) ## PluginFactory外掛庫 - 專案地址: - [Gitee](https://gitee.com/WuYeCai/pluginfactory) - [Github](https://github.com/xfrogcn/Xfrogcn.PluginFactory) - Nuget包: - [Xfrogcn.PluginFactory](https://www.nuget.org/packages/Xfrogcn.PluginFactory/) 實現包,在主專案中引用 - [Xfrogcn.PluginFactory.Abstractions](https://www.nuget.org/packages/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地址](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方法啟用外掛庫 ```c# var builder = Host.CreateDefaultBuilder(args); builder.UsePluginFactory(); ```     **UsePluginFactory**具有多個過載版本,詳細請檢視[API](https://gitee.com/WuYeCai/pluginfactory/blob/master/doc/api.md)文件 預設配置下,將使用程式執行目錄下的**Plugins**目錄作為外掛程式集目錄, 使用宿主配置檔案作為外掛配置檔案(通常為appsettings.json) 你也可以通過使用帶有 **Assembly** 或 **IEnumerable<Assembly>** 引數的版本直接傳入外掛所在的程式集 #### 通過IServiceCollection的AddPluginFactory方法啟用外掛庫 ```c# var builder = Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddPluginFactory(); }); ```     **AddPluginFactory**具有多個過載版本,詳細請檢視[API](https://gitee.com/WuYeCai/pluginfactory/blob/master/doc/api.md)文件 預設配置下,將使用程式執行目錄下的**Plugins**目錄作為外掛程式集目錄 *注意:* AddPluginFactory方法**不會**使用預設的配置檔案作為外掛配置,你需要顯式地傳入**IConfiguration**, 如果是在 ASP.NET Core 環境中,你可以在Startup類中直接獲取到 ### 編寫外掛 外掛是實現了IPlugin介面的類,在外掛庫中也提供了PluginBase基類,一般從此類繼承即可。標準外掛具有啟動和停止方法,通過**IPluginFactory**進行控制。 要編寫外掛,一般遵循以下步驟: 1. 建立外掛專案(.NET Core 類庫),如TestPluginA 1. 新增**Xfrogcn.PluginFactory.Abstractions**包 ```nuget dotnet add package Xfrogcn.PluginFactory.Abstractions ``` 1. 建立外掛類,如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獲取注入服務* 1. 通過**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(); 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(); } } ``` ### 使用外掛配置     外掛支援 .NET Core 擴充套件庫中的Options及Configuration機制,你只需要從**SupportConfigPluginBase<TOptions>**類繼承實現外掛即可,其中TOptions泛型為外掛的配置型別。外掛配置自動從宿主配置或啟用外掛工廠時傳入的配置中獲取,外掛配置位於配置下的Plugins節點,該節點下以外掛類名稱或外掛別名(通過**PluginAttribute**特性指定)作為鍵名,此鍵之下為外掛的配置,如以下配置檔案: ```appsettings.json { "Plugins": { "PluginA": { "TestConfig": "Hello World" }, } } ``` 擴充套件PluginA實現配置: 1. 定義配置類,如PluginOptions ```c# public class PluginOptions { public string TestConfig { get; set; } } ``` 2. 實現外掛 ```c# [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注入外掛程式集: ```c# context.ServiceCollection.AddMvcCore() .AddApplicationPart(typeof(Plugin).Assembly); ```