CodeDom 是啥東東?Html Dom聽過吧,XML Dom聽過吧。DOM一般可翻譯為 文檔對象模型,那 Code + DOM呢,自然是指代碼文檔模型了。如果你從來沒接觸過 CodeDom,你大概可以根據這個名字,推斷它應該和代碼文檔模型有關。
這推斷是靠譜的,CodeDom的功能,老周厚着臉皮把它歸結為兩大部分:
1、生成代碼文檔。這個聽起來很玄?不玄,就是咱們在VS里常常耍的代碼生成,比如你添加了一個服務引用,VS會幫你生成一個客戶端代理類。
2、動態編譯程序集。這個也好懂,就是動態編譯。
很多朋友一遇到這個就怕,很難,很復雜。其實不然,CodeDom並不難,把思路理清了就好學了,這個事咱們暫時不談,先說說老周要寫的這系列文章吧,簡單拋個磚,引個玉,免得大伙到時候向老周扔磚。
其實老周在幾個世紀前曾在其他的博客上寫過 CodeDom 相關的文章,大家也不要去人肉那些文章了,都是很膚淺很爛的文章,只是XX幾筆就寫完了,初學者朋友肯定看不懂的。沒辦法了,幾個世紀前老周的編程水平比較爛,有時候翻開自己以前寫的東西,都覺得很搞笑,自己當年怎么寫這么SB的文章。
為了讓更多朋友能夠看懂,也為了向傳統的編程教學方式發起挑戰,有關CodeDom這系列文章,老周計划開啟【廢話模式】,老周會盡可能進行細致的講解,到時候你不要覺得煩,廢話會很多的。正因為廢話多,所以一兩篇文章肯定寫不完的,至少得來個中篇小說的容量才行。
============================================
好,下面開始講廢話。
作為廢話系列的第一篇,老周不會馬上讓你動手寫代碼的,既然是跟代碼文檔有關的東西,那就先復習一下代碼的基礎知識,很重要的,趕緊划重點,期末考試一定會考的。我的大學老師在上復習課的時候,老喜歡說這句話。記得當年老周就是不划重點,所以考了48.5分,然后被抓去補考,補考考了66分,形式上不用重修,於是就天下大吉了。上大學時,老周對考試從來都沒認真過,包括考英語四級,作文里面還寫上粗口,不知道閱卷老師看到之后會不會血壓上升。
細細想一想,真不知道考試是為了什么,考60分又如何,考100分又如何,不還是一樣嗎。老周是出了名的上課不聽課,復習不認真,考試不重視,哪怕面對高考也一樣。但是老周絕不是不認真學習的人,只是跟賈寶玉差不多,怕看正經書,對於正經書以外的很多東西,老周反而很用功。
老周這個人,沒什么優點,長得不帥(眼睛小,嘴巴扁,鼻子高),又不富(當年那張中信銀行卡上時刻保持余額1.33元),1米78的身材也不高。唯一的優點就是興趣廣,愛好多,雜學旁收,從不客氣,只要別讓我讀教材做考試題就行。
所以當年有妹子就寫了一首詩來形容老周:
不愛煙酒不羡富,苦學逸少子昂書。
酷喜上課看雜志,最怕臨考背試題。
偶得仙樂歌一闕,沉思漫筆有洞天。
CodeDom支持如C#、VB、C++、JScript這幾種語言的代碼生成,當然,必須是生成CLR能認識的代碼,所以這里頭的C++主要是托管C++。
現在,你開始回憶一下,滿懷深情地回憶一下,一個CLR程序集里面有什么?由於在VS里面,一個項目就是一個程序集,或者你可以想一下,一個項目的代碼里面有啥。
咱們從外向里一層一層的刷一下。
A、一個項目中是不是有N個命名空間?想起來了吧,而命名空間里面可以包括命名空間,不過,CodeDom中不使用嵌套命名空間,比如,System和System.IO可以認為是兩個單獨的命名空間。
B、然后,大伙再想想,一個命名空間下有啥。類型,好,類型又有多少種?數一數,類、結構、枚舉、接口、委托。
C、類型下面有什么?對,成員,那么類型成員有幾種。再數一數,構造函數、字段、屬性、方法、事件。
1)如果類型是泛型類型,還會包含若干泛型列表,泛型參數可能還帶有約束。
2)如果成員是方法,會包含有輸入參數、輸出參數或返回值;對於屬性成員,會有get和set訪問器。對於索引器,會有索引變量。
D、類型成員下包含語句集合(Statement),通常翻譯為語句比較好聽。常規代碼語句以英文的分號(;)結束,這個大家都很熟悉了,當然,像if、while、for這些語句比較特別,它們往往包含多個條件。
E、語句是由表達式和運算符(操作符)組成。
比如,這樣就是一個表達式,常量表達式。
300
這樣就是一個語句,賦值語句。
k = 300;
這是語句,它包括一個 = 運算符(賦值運算符),一個變量引用表達式(k),以及一個常量表達式(300)。
有一個語句大家要注意,就是這樣:
double x = 0.0021d;
別看它很簡單,別看它是很基礎的知識,這里面的門道你還真未必已經掌握。
它是一個復合語句,其實它包含兩個語句:聲明語句(double x;),賦值語句(x = 0.0021d)。如果拆開來,可以這樣寫。
double x; x = 0.0021d;
而 double x = 0.0021d 是在變量聲明時順便進行初始化。在兩種寫法在 CodeDom 代碼生成中是應當區別,這個后續的文章中老周會講的,現在你暫時了解一下。
好,代碼的結構大觀我們復習完了,老周保證你期末考試能考95分。
既然是要講CodeDom的,就得把代碼結構中的各個對象與CodeDOM類型對號入座,這樣可以方便大家熟悉CodeDom模型。
來,先喝杯牛奶,做好准備,下面開始接觸 CodeDom了。
=========================================
CodeDom 的根容器是 CodeCompileUnit,它是一個編譯單元,這個類你必須認識,不然以后就無法CodeDom了,如果要進行動態編譯,就應該用一個編譯單元來編譯,不能用一句代碼來編譯,因為這樣生成的程序沒有實際意義,也不能運行。
編譯單元你可以把它類比一個VS項目,一個程序集。所以,你會看到,CodeCompileUnit 類有一個 Namespaces 屬性,這使得一個編譯單元可以包含 N 個命名空間。
一個命名空間可以用 CodeNamespace 類來表示,Comments 用來設置給命名空間寫的注釋,Imports就是這個命名空間中要引入的其他命名空間,就是C#中的 using,VB中的 Import,托管C++中的 using。
一個 CodeNamespace 類公開了 Types 屬性,表示某個命名空間下的類型集合。要聲明一個類型,使用 CodeTypeDeclaration 類,至於定義的是類,是接口,還是枚舉,可以用類的屬性來決定。例如IsInterface指定是否為接口,IsClass指定是否為類,IsEnum指定是否為枚舉等。如果類是從其他類型派生的,或者實現接口,那可以向BaseTypes屬性添加基類型。如果基類是Object,可以忽略。
但是,委托類型的聲明比較特殊,它使用 CodeTypeDelegate 類。
一個類型之下包含的是類型成員,它們對應的CodeDom類有:CodeMemberField(字段)、CodeMemberProperty(屬性)、CodeMemberMethod(方法)、CodeMemberEvent(事件)。
注意,表示類型構造函數有兩個類。如果是靜態構造函數,因為它是屬於類型而非實例,所以要用 CodeTypeConstructor;對於普通面向實例的構造函數要使用 CodeConstructor。
好了,今天就講到這里吧,講多了,大伙會接受不了。下一篇文章,老周再介紹代碼表達式和代碼語句。