動態編譯並執行程式碼是 .NET 提供的強大擴充手段,適用於模板生成、外掛邏輯擴充等場景。核心命名空間為 System.CodeDom.Compiler 與 Microsoft.CSharp(或 Microsoft.VisualBasic),搭配反射實現動態呼叫。
CSharpCodeProvider 實例CompilerParameters(參考組件、GenerateInMemory = true)CompileAssemblyFromSource 編譯Assembly.CreateInstance 建立實例InvokeMember 呼叫方法string strSourceCode = this.txtSource.Text;
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
parameters.GenerateInMemory = true;
CompilerResults results = provider.CompileAssemblyFromSource(parameters, strSourceCode);
if (results.Errors.HasErrors) { /* 處理錯誤 */ return; }
Assembly asm = results.CompiledAssembly;
object obj = asm.CreateInstance("Dynamicly.HelloWorld");
object[] args = new object[] { "Allan." };
string result = (string)obj.GetType().InvokeMember("GetTime", BindingFlags.InvokeMethod, null, obj, args);
this.txtResult.Text = result;
測試程式碼:
using System;
namespace Dynamicly
{
public class HelloWorld
{
public string GetTime(string strName)
{
return "Welcome " + strName + ", Check in at " + DateTime.Now.ToString();
}
}
}

基本作法會將組件載入當前 AppDomain,無法卸載,長期執行會導致記憶體洩漏。解決方案:
AppDomainGenerateInMemory = false,指定 OutputAssembly)IRemoteInterface 及工廠 RemoteLoaderFactory : MarshalByRefObjectAppDomain.Unload 卸載域並刪除 DLL// 介面與工廠(獨立組件 RemoteAccess.dll)
public interface IRemoteInterface { object Invoke(string method, object[] parameters); }
public class RemoteLoaderFactory : MarshalByRefObject
{
public IRemoteInterface Create(string assemblyFile, string typeName, object[] constructArgs)
{
return (IRemoteInterface)Activator.CreateInstanceFrom(assemblyFile, typeName, false,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance,
null, constructArgs, null, null, null).Unwrap();
}
}
// 主程式調用
AppDomainSetup setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory };
AppDomain domain = AppDomain.CreateDomain("MyAppDomain", null, setup);
CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("RemoteAccess.dll");
parameters.GenerateInMemory = false;
parameters.OutputAssembly = "DynamicalCode.dll";
CompilerResults results = provider.CompileAssemblyFromSource(parameters, strSourceCode);
// ... 錯誤處理 ...
RemoteLoaderFactory factory = (RemoteLoaderFactory)domain.CreateInstanceAndUnwrap("RemoteAccess", "RemoteAccess.RemoteLoaderFactory");
IRemoteInterface remote = factory.Create("DynamicalCode.dll", "Dynamicly.HelloWorld", null);
string result = (string)remote.Invoke("GetTime", new object[] { "Allan." });
remote = null;
AppDomain.Unload(domain);
File.Delete("DynamicalCode.dll");
客戶端類別需繼承 MarshalByRefObject 並實作 IRemoteInterface:
public class HelloWorld : MarshalByRefObject, IRemoteInterface
{
public object Invoke(string method, object[] parameters)
{
return this.GetType().InvokeMember(method, BindingFlags.InvokeMethod, null, this, parameters);
}
public string GetTime(string strName) => "Welcome " + strName + ", Check in at " + DateTime.Now;
}
透過獨立 AppDomain 載入動態組件,可實現組件卸載、記憶體控制與安全性隔離,是生產環境動態編譯的最佳實踐。