標籤:alt 產生 c# img reference var 輸出 索引 技術分享
在開始正題之前,先補充一點前面的內容。
在方法中,如果要引用方法參數,前面的樣本中,老周使用的是 CodeVariableReferenceExpression 類,它用於引用變數,也適用於引用方法參數。除了這個類,還可以使用 CodeArgumentReferenceExpression 類,這個類是專為方法參數引用而設計,其實用起來也和變數引用一樣。請看看下面的例子。
CodeMemberMethod m = new CodeMemberMethod(); m.Name = "Test"; // 輸出參數 CodeParameterDeclarationExpression p = new CodeParameterDeclarationExpression(typeof(int), "a"); p.Direction = FieldDirection.Out; m.Parameters.Add(p); // 指派陳述式 CodeAssignStatement ass = new CodeAssignStatement(); ass.Left = new CodeArgumentReferenceExpression(p.Name); ass.Right = new CodePrimitiveExpression(100000); m.Statements.Add(ass); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); CodeGeneratorOptions opt = new CodeGeneratorOptions { BracingStyle = "C" }; provider.GenerateCodeFromMember(m, Console.Out, opt);
Test 方法帶有一個輸出參數a,int類型,方法體中給參數a賦值。上面代碼執行後,產生的程式碼如所示。
============================================
好,進入主題,今天咱們來聊一聊“索引”這玩意兒。通常,使用索引的類型有:數組、List、雜湊表/字典等。使用索引的類型成員有索引器。索引器可能不多見,其實跟屬性很像。
先來看看數組的初始化方法。初始化數組是一類運算式,主要用到 CodeArrayCreateExpression 類。
看一個簡單的例子。
CodeArrayCreateExpression ce = new CodeArrayCreateExpression(); ce.CreateType = new CodeTypeReference(typeof(string)); ce.Size = 5; CodeDomProvider p = CodeDomProvider.CreateProvider("C#"); p.GenerateCodeFromExpression(ce, Console.Out, null);
CreateType 屬性用來指定數組的類型,本例中類型為string,Size屬性指定數組的大小。得到的代碼如所示。
由於不是所有語言都支援多維陣列和嵌套數組,所以,目前來說,CodeDom並不能執行個體化多維陣列。不過也沒關係,畢竟N維數組和嵌套數組很少會用得上。
有時候,在執行個體化數組對象的時候就順便對元素進行初始化,可以將初始化元素的運算式添加到 Initializers 集合中。請看下面例子。
CodeArrayCreateExpression arrce = new CodeArrayCreateExpression(); arrce.CreateType = new CodeTypeReference(typeof(int)); // 初始化元素 arrce.Initializers.Add(new CodePrimitiveExpression(1)); arrce.Initializers.Add(new CodePrimitiveExpression(3)); arrce.Initializers.Add(new CodePrimitiveExpression(5)); // 聲明變數 CodeVariableDeclarationStatement vd = new CodeVariableDeclarationStatement(); vd.Name = "x"; vd.Type = new CodeTypeReference(typeof(int[])); vd.InitExpression = arrce;
最後使用 CodeVariableDeclarationStatement 產生一句完整的變數聲明語句,初始設定變數時就用CodeArrayCreateExpression運算式。
產生的程式碼如所示。
要訪問某個陣列變數的指定索引處的值,可以用 CodeArrayIndexerExpression 類。
CodeArrayIndexerExpression aiexp = new CodeArrayIndexerExpression(); aiexp.TargetObject = new CodeVariableReferenceExpression("x"); aiexp.Indices.Add(new CodePrimitiveExpression(0));
TargetObject屬性用來設定對陣列變數的引用,Indices集合用來添加索引參考資料表達式,數組的索引都是整數,所以,應當用以下運算式:
new CodePrimitiveExpression(<整數值>)
上面樣本產生的程式碼如所示。
=================================================
下面咱們看看索引器。
訪問索引器最典型的一個應用是字典。下面例子將產生三個語句,其中,第一句是聲明被初始化一個字典變數,第二句和第三句都是向字典變數添加元素。
// 聲明並初始化字典變數 CodeVariableDeclarationStatement vd = new CodeVariableDeclarationStatement(); vd.Type = new CodeTypeReference(typeof(Dictionary<string, string>)); vd.Name = "dic"; vd.InitExpression = new CodeObjectCreateExpression(typeof(Dictionary<string, string>)); // 給字典對象添加元素 // 左邊:索引引用 // 右邊:值 CodeAssignStatement ass = new CodeAssignStatement(); ass.Left = new CodeIndexerExpression(new CodeVariableReferenceExpression(vd.Name), new CodePrimitiveExpression("a")); ass.Right = new CodePrimitiveExpression("cake"); CodeAssignStatement ass1 = new CodeAssignStatement(); ass1.Left = new CodeIndexerExpression(new CodeVariableReferenceExpression(vd.Name), new CodePrimitiveExpression("b")); ass1.Right = new CodePrimitiveExpression("bird"); CodeDomProvider prd = CodeDomProvider.CreateProvider("cs"); prd.GenerateCodeFromStatement(vd, Console.Out, null); prd.GenerateCodeFromStatement(ass, Console.Out, null); prd.GenerateCodeFromStatement(ass1, Console.Out, null);
引用某個執行個體的索引器,應使用 CodeIndexerExpression 類。TargetObject屬性用來指定要引用的對象,通常是變數引用,Indices屬性是索引集合,用來指定要訪問的索引。這些屬性的值可以直接向CodeIndexerExpression類的建構函式傳遞。
本例產生的程式碼如下。
System.Collections.Generic.Dictionary<string, string> dic = new System.Collections.Generic.Dictionary<string, string>();dic["a"] = "cake";dic["b"] = "bird";
如果要給自訂的型別宣告索引器,要用 CodeMemberProperty 類,因為索引器與屬性相似。還是用例子說話吧。
CodeTypeDeclaration td = new CodeTypeDeclaration("Sample"); td.Attributes = MemberAttributes.Public; // 索引器 CodeMemberProperty mb = new CodeMemberProperty(); mb.Type = new CodeTypeReference(typeof(string)); mb.Name = "item"; mb.Attributes = MemberAttributes.Public | MemberAttributes.Final; // 索引參數 mb.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "k")); td.Members.Add(mb); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); provider.GenerateCodeFromType(td, Console.Out, null);
這裡有個地方要注意,就是索引器成員的名字,為了相容各種語言,較合適的做法是把它命名為“item”或“Item”(不分大小寫),這樣一來,產生C#代碼時,就能夠產生 this[int k] 這樣的文法,只有這樣的文法才能被認為是索引器。
產生的程式碼如所示。
好了,今天對索引器代碼產生相關的內容就扯到這裡了,下一篇文章,老周就繼續和大家聊聊條件陳述式與迴圈語句。
開飯了……
【.net 深呼吸】細說CodeDom(7):索引器