top of page
作家相片JYTEK Taiwan

C# Plugin架構範例

已更新:10月21日

範例下載



參考連結


C# Plugin 總覽

在典型的工廠模式中,產生的物件所依賴的各種dll, package都會包含在csproj專案內,即使在應用程式內沒有使用,還是會被專案引用, 無形中增加專案的風險。


    var instance=Factory.New();
    var msg = instance.ShowMessage();
    Console.WriteLine($"[{name}]{msg}");
    Console.ReadKey();

C# Plugin設計具備以下特性

  1. 工廠所產生的物件在執行階段(run-time)下可擴充, 主程式不須重新編譯

  2. 將應用程式中與實作的物件關聯解耦, 實現模組化的框架

  3. 模組化的物件依賴獨立, 應用程式維持最小化

  4. 快速切換不同模組, 而不需修改應用程式


工作原理


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

21 次查看0 則留言

最新文章

查看全部

全新DAQ數據採集卡 - PXIe/PCIe 5500系列

簡儀科技發布全新JY 5500系列DAQ數據採集卡, 針對多功能測量需求的客戶提供完整的產品解決方案。JY 5500系列共有四種型號(5510, 5511, 5515, 5516)以及兩種介面(PXIe, PCIe)可搭配, 未來也會為客戶提供USB的介面選擇。...

Comments


bottom of page