動態編譯讓應用程式具備腳本化擴充能力。本文封裝 CSharpProvider 類別,整合原始碼編譯、實例建立、應用程式域隔離與 Visual Studio 偵錯支援,解決記憶體洩漏與重複編譯效能問題。
public string AssemblyFileName { get; set; } // 輸出組件名稱
public CompilerParameters CompilerParameters { get; } // 編譯參數
public StringCollection References { get; } // 參考組件集合
public Encoding SourceCodeFileEncoding { get; set; } // 原始碼檔案編碼
智慧參考管理:System.* 命名空間自動載入;使用者組件若未手動指定,嘗試依命名空間推測組件檔名。
// 從字串編譯
public bool Compile(string code)
// 從檔案編譯(支援偵錯)
public bool CompileFromFile(string sourceCodeFileName)
// 建立實例(依型別全名或介面型別)
public object CreateInstance(string code, string typeFullName)
public object CreateInstanceFromFile(string fileName, string typeFullName)
動態載入的程式碼必須繼承 MarshalByRefObject,否則主應用程式域會持有子域參考導致無法卸載:
[Serializable]
public class HelloWorld : MarshalByRefObject, IHelloWorld {
public string Say() => "Hi";
}
封裝類別在重新編譯或物件銷毀時自動卸載 AppDomain 釋放記憶體。
三個必要條件:
CompilerParameters.IncludeDebugInformation = trueCompileFromFile 偵錯)System.Diagnostics.Debugger.Break()
CSharpProvider 類別結構圖
動態程式碼偵錯示意:命中 Debugger.Break() 中斷點