.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

嗯,大概就是這樣 ;-)