如何將一段文本編譯成C#內存程序的過程

string code = null;

// 1. 生成要編譯的代碼。(示例爲了簡單直接從程序集內的資源中讀取)
Stream stram = typeof(CodeDOM).Assembly
            .GetManifestResourceStream("TestOptimizeReflection.用戶手冊.txt");
using( StreamReader sr = new StreamReader(stram) ) {
    code = sr.ReadToEnd();
}

//Console.WriteLine(code);

// 2. 設置編譯參數,主要是指定將要引用哪些程序集
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("OptimizeReflection.dll");

// 3. 獲取編譯器並編譯代碼
// 因爲個人代碼使用了【自動屬性】特性,因此須要 C# .3.5版本的編譯器。
// 獲取與CLR匹配版本的C#編譯器能夠這樣寫:CodeDomProvider.CreateProvider("CSharp")

Dictionary<string, string> dict = new Dictionary<string, string>();
dict["CompilerVersion"] = "v3.5";
dict["WarnAsError"] = "false";

CSharpCodeProvider csProvider = new CSharpCodeProvider(dict);
CompilerResults cr = csProvider.CompileAssemblyFromSource(cp, code);

// 4. 檢查有沒有編譯錯誤
if( cr.Errors != null && cr.Errors.HasErrors ) {
    foreach( CompilerError error in cr.Errors )
        Console.WriteLine(error.ErrorText);

    return;
}

// 5. 獲取編譯結果,它是編譯後的程序集
Assembly asm = cr.CompiledAssembly;

整個過程分爲5個步驟,它們已用註釋標識出來了,這裏再也不重複了。html

如何調用編譯結果

前面的代碼把一段文本字符串編譯成了程序集,如今還有最後一個問題:如何調用編譯結果?ide

答案:有二種方法,
1. 直接調用方法。
2. 實例化程序集中的類型,以接口方式調用方法。
其實這二種方法都須要使用反射,用反射定位到要調用的類型和方法。code

第一種方法要求在生成代碼時,生成的類名和方法名是明確的,在調用方法時,咱們有二個選擇:
1. 用反射的方式調用(這裏只是一次反射)。
2. 爲方法生成委託(用上篇博客介紹的方法),而後基於委託調用。htm

第二種方法要求在生成代碼時,首先要定義一個接口,保證生成的代碼能實現指定的接口,
然而用反射找到要調用的類型名稱,用反射或者委託調用構造方法建立類型實例,最後基於接口去調用。
咱們熟悉的ASPX頁面就是採用了這種方式來實現的。blog

這二種方法也能夠這樣區分:
1. 若是生成的方法是靜態方法,應該選擇第一種方法。
2. 若是生成的方法是實例方法,那麼選擇第二種方法是合理的。接口

對於前面的示例,我採用了第一種方法了,由於類名和方法名稱都是事先肯定的並且實現起來比較簡單。資源

// 6. 找到目標方法,並調用
Type t = asm.GetType("OptimizeReflection.用戶手冊");
MethodInfo method = t.GetMethod("Main");
method.Invoke(null, null);

 參考:http://www.cnblogs.com/fish-li/archive/2013/02/24/2924673.html#_labelStart字符串

相關文章
相關標籤/搜索