2010-03-02 40 views
41

什麼是使用Reflection.Emit的庫對CodeDOM的在運行時動態生成代碼的一些優點/缺點?Reflection.Emit的VS CodeDOM的

我想基於現有的XML格式的運行時元數據在系統中生成一些(相對複雜)的動態類。我將生成擴展應用程序組合中的現有類,實現更多接口,添加方法以及覆蓋虛擬和抽象成員的類。

我想確保我選擇合適的技術之前,我得到過深入實施。有關這些不同的代碼生成技術如何不同的任何信息都會有所幫助。此外,任何有關簡化或簡化工作的開放源代碼庫信息都可能會有用。

+1

在閱讀本文時,NHibernate是我第一個想到的人。值得一看的是他們如何做到這一點? – quip 2010-03-02 21:32:02

+1

我其實是在看那個。他們使用Reflection.Emit,但不清楚他們爲什麼選擇CodeDOM和CodeDOM。 – LBushkin 2010-03-02 22:02:02

回答

50

我想的CodeDOM和Reflection.Emit的關鍵點是以下:

  • 的CodeDOM生成C#源代碼,並生成代碼時被包括作爲一個解決方案的一部分,並在編譯通常使用IDE(例如,LINQ to SQL類,WSDL,XSD都以這種方式工作)。在這種情況下,您還可以使用部分類來自定義生成的代碼。效率較低,因爲它生成C#源代碼,然後運行編譯器解析它(再次!)並編譯它。您可以使用相對較高級的構造(類似於C#表達式&語句)來生成代碼,例如循環。

  • Reflection.Emit生成一個IL,因此它直接生成一個程序集,該程序集也只能存儲在內存中。結果是效率更高。您必須生成低級IL代碼(值存儲在堆棧中;循環必須使用跳轉來實現),因此生成更復雜的邏輯有點困難。

一般來說,我認爲Reflection.Emit的通常被認爲在運行時生成的代碼的首選方式,而生成代碼時之前編譯時是優選的CodeDOM。在你的場景中,它們都可能工作正常(儘管CodeDOM可能需要更高的權限,因爲它實際上需要調用C#編譯器,這是任何.NET安裝的一部分)。

另一種選擇是使用Expression class。在.NET 4.0中,它允許您生成等效於C#表達式和語句的代碼。但是,它不允許你生成一個類。因此,您可以將其與Reflection.Emit(用於生成將實現委託給使用Expression生成的代碼的類)結合使用。對於某些場景,您可能並不需要完整的類層次結構 - 通常,動態生成的代表(如Dictionary<string, Action>)的字典可能足夠好(但當然,這取決於您的確切場景)。靶向的CodeDOM

+0

這是我的理解CodeDOM也可以[在內存中生成代碼](http://msdn.microsoft.com/en-us/library/system.codedom.compiler.compilerparameters.generateinmemory.aspx)? – 2011-09-26 12:38:13

+0

您能否詳細說明如何使用CodeDom的部分類?如果我的研究表明任何事情,那就是你根本不能使用'partial':它甚至不是'TypeAttributes'枚舉中的一個選項。 – 2014-04-06 20:31:54

+0

完整答案。謝謝。 – nawfal 2015-08-19 14:27:46

14

代碼往往是更易於維護,因爲你生成的C#代碼,而不是IL(更多的人可以閱讀C#比IL)。此外,如果你的CodeDom代碼錯誤,你會得到一個編譯器錯誤;如果您生成無效的IL,則會發生致命異常或崩潰。

但是,因爲CodeDom調用csc.exe編譯器,所以讓代碼準備好使用會稍慢一些。使用Reflection.Emit,您可以直接在內存中生成代碼。

CodeDom對於大多數事情來說可能是很好的; XmlSerializer和WinForms設計器使用它。

+0

XmlSerializer使用CodeDOM的是什麼?對不起,我可以在Reflector中查看,但我很懶,因爲我的注意力分散在許多其他問題中,並且自從你回答了這個問題之後,我假設你已經投入了時間,所以你可以簡單地鍵入答案,而不用花費太多時間無論是。 – 2013-12-02 07:19:45

+0

@ WaterCoolerv2如果我不得不猜測,他們會構建一個程序集來讀取/寫入目標類型。我曾經被帶入一個帶有巨大反射數據訪問層的項目。這是狗慢,所以用戶恨它,但沒有人知道如何解決它。我通過緩存和發射的結合實際上實現了它。除了將緩慢的反射切割出圖外,還可以通過首先檢查類型並將適當的操作碼直接發送到方法中來消除開銷,而不是在序列化過程中分支或調用專門的代理。 – Daniel 2018-01-08 14:12:02