主頁 > .NET開發 > 一個.NET Core下的開源插件框架

一個.NET Core下的開源插件框架

2020-11-05 14:06:24 .NET開發

    插件模式歷史悠久,各種中大型軟體基本上都會實作插件機制,以此支持功能擴展,從開發部署層面,插件機制也可實作功能解耦,對于并行開發、專案部署、功能定制等都有比較大的優勢,

    在.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)
你也可以通過使用帶有 AssemblyIEnumerable<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進行控制,

要撰寫插件,一般遵循以下步驟:

  1. 創建插件專案(.NET Core 類別庫),如TestPluginA

  2. 添加Xfrogcn.PluginFactory.Abstractions

     ```nuget
     dotnet add package Xfrogcn.PluginFactory.Abstractions
     ```
    
  3. 創建插件類,如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獲取注入服務

  4. 通過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實作配置:

  1. 定義配置類,如PluginOptions

     ```c#
     public class PluginOptions
     {
         public string TestConfig { get; set; }
     }
     ```
    
  2. 實作插件

     ```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);
         }
     ```
    

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

  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);
```

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/203281.html

標籤:.NET技术

上一篇:大一作業求解答

下一篇:Visual Studio中Git的簡單使用

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more