範例下載
參考連結
C# Plugin 總覽
在典型的工廠模式中,產生的物件所依賴的各種dll, package都會包含在csproj專案內,即使在應用程式內沒有使用,還是會被專案引用, 無形中增加專案的風險。
var instance=Factory.New();
var msg = instance.ShowMessage();
Console.WriteLine($"[{name}]{msg}");
Console.ReadKey();
C# Plugin設計具備以下特性
工廠所產生的物件在執行階段(run-time)下可擴充, 主程式不須重新編譯
將應用程式中與實作的物件關聯解耦, 實現模組化的框架
模組化的物件依賴獨立, 應用程式維持最小化
快速切換不同模組, 而不需修改應用程式
工作原理
Plugin結構分為兩個部分 - PluginBase (抽象類) PluginBase類設計為interface, 由實作類繼承 - PluginA (實作類)
主程式引用/使用的是抽象類,抽象類需要定義該有的行為及參數
操作步驟
Step1. 設計 C# PluginBase 抽象類
新建一個ClassLibrary (.NET Framework)
修改類名稱為PluginBase
將Class1.cs更名為PluginBase.cs
將PluginBase.cs內容修改為以下內容
using System.Reflection;
using System;
using System.Linq;
namespace PluginBase
{
public interface IPluginBase
{
string Name { get; } //Name of the instance
string ShowMessage(); //Display the message
}
/// <summary>
/// This is the factory class used to generate Plugin instance
/// </summary>
public static class PluginBaseFactory
{
/// <summary>
/// Create IPluginBase by the path
/// </summary>
/// <param name="path">dll path</param>
/// <returns>IPluginBase instance</returns>
public static IPluginBase Create(string path)
{
try
{
//Load the dll into memory
var assem = Assembly.LoadFrom(path);
//Search the type that inherits from IPluginBase
Type t = assem.GetTypes().First(
y => typeof(IPluginBase).IsAssignableFrom(y));
//Create instance from the type
var instance = Activator
.CreateInstance(t) as IPluginBase;
//return the instance
return instance;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
Step2. 設計 C# PluginA 實作類
新增一個ClassLibrary(.NET Framework)
修改類名為PluginA
修改Class1.cs名稱為PluginA.cs
添加引用(PluginBase.csproj)到此專案
將內容修改如下
namespace PluginA
{
public class PluginA : PluginBase.IPluginBase
{
public string Name => "PluginA";
public string ShowMessage()
{
return "This is PluginA instance";
}
}
}
將專案unload後, 在PluginA.csproj檔案中Property Group內新增一行
<EnableDynamicLoading>true</EnableDynamicLoading>
在pluginA.csproj檔案中引用PluginBase.csproj的段落中新增兩行
<ProjectReference Include="..\PluginBase\PluginBase.csproj">
...
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
reload專案
Step3. 撰寫基本範例
將PluginBase以及PluginA兩個專案執行build動作
新建一個Console專案
變更名稱為PluginDEMO
添加引用PluginBase.csproj到專案內
將程式碼修改如下
using PluginBase;
using System;
namespace PluginDEMO
{
internal class Program
{
static void Main(string[] args)
{
//this is the path for PluginA
var path = @"..\..\..\PluginA\bin\Debug\PluginA.dll";
//Use factory to generate the instance
var plugin = PluginBaseFactory.Create(path);
var name=plugin.Name;
var msg = plugin.ShowMessage();
Console.WriteLine($"[{name}]{msg}");
Console.ReadKey();
}
}
}
PluginDEMO的Console應用程式只引用了PluginBase的抽象類,PluginA則是在執行的時候動態從檔案系統裡生成。主程式可以在不曉得實作類的情況下使用Name的屬性以及ShowMessage()的方法,代表Name屬性和ShowMessage()的方法的實作是在PluginA修改, 而不影響到主程式的運作。執行後會得到以下結果
> [PluginA]This is PluginA instance
Comments