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字符串