Kan-Ru Chen's Weblog

.NET - Load Plugins

寫 c/c++ 的時候,可以用 dlopen 來讀入 .so/.dll 檔當作 plugin 用,寫 perl 的時候用 require 就可以把另一個 perl module 讀到記憶體,elisp 也有類似的用法,.NET 則提供了 System.Reflection.Assembly 類別來處理這樣的事。

首先為了統一 Plugin 的介面,我們可以定義幾個 Plugin 專用的 interface:

    // PluginInterfaces.dll
    namespace Plugin.Interfaces
        public interface IPlugin
            Calculate (input: int) : int

然後 Plugin 的實做寫在另一個 Assembly:

    // Plugins.dll
    using Plugin.Interfaces
    namespace Plugin.Test
        public class Test1 : IPlugin
            public Calculate (input: int) : int
                input * 2
        public class Test2 : IPlugin
            public Calculate (input: int) : int
                input + 3

然後主程式就可以把這些 plugins 動態的讀近來:

    // Run.exe
    using System
    using System.Reflection
    using Plugin.Interfaces
    public module R
        public Main (args: array[string]) : void
            def p = Assembly.LoadFile (args[0]).CreateInstance (args[1]) :> IPlugin
            Console.WriteLine (p)
            Console.WriteLine (p.Calculate (100))

實際執行的結果:

    $ ncc PluginInterfaces.n -out:PluginInterfaces.dll -target:library
    $ ncc Plugins.n -ref:PluginInterfaces.dll -out:Plugins.dll -target:library
    $ ncc Run.n -ref:PluginInterfaces.dll -out:Run.exe
    $ ./Run.exe Plugins.dll Plugin.Test.Test1
    Plugin.Test.Test1
    200
    $ ./Run.exe Plugins.dll Plugin.Test.Test2
    Plugin.Test.Test2
    103

嗯,大概就是這樣 ;-)