有人會問,爲啥 CodeDom 不會生成 switch 語句,爲啥沒生成 while 語句之類。要注意,CodeDom只關心代碼邏輯,而不是語法,語法是給寫代碼的人用的。若是用.net的「反編譯」工具的朋友會知道,你用while語句寫了一段代碼,而後編譯生成程序集,再用工具把代碼「反」出來,此時你會發現,你原來寫的是while語句,但出來的是for語句,道理是同樣的,「反編譯」工具只關心代碼的執行邏輯,而不是語法。因此,你天然沒法用 CodeDom 來生成var關鍵字來聲明變量,也沒法生成用 Lambda 表達式表示的方法,也不能生成僅有get和set的屬性定義語法。ide
所以,你們不要把語法和邏輯搞混。工具
先來介紹一下分支,分支語句相似 if 語句,由 CodeConditionStatement 類表示,它須要三個要素:spa
一、條件,用於判斷給定的表達式是否爲true。.net
二、當條件成立時所執行的代碼。3d
三、當條件不成立時所執行的代碼。code
下面舉個例子,讓某數除以2,並取模(即取餘),若是結果爲0,即爲偶數,不然爲奇數。代碼以下。blog
// 取模運算 CodeBinaryOperatorExpression modexp = new CodeBinaryOperatorExpression(); modexp.Operator = CodeBinaryOperatorType.Modulus; modexp.Left = new CodePrimitiveExpression(6); modexp.Right = new CodePrimitiveExpression(2); // 相等運算 CodeBinaryOperatorExpression eqexp = new CodeBinaryOperatorExpression(); eqexp.Operator = CodeBinaryOperatorType.IdentityEquality; eqexp.Left = modexp; eqexp.Right = new CodePrimitiveExpression(0); // 分支語句 CodeConditionStatement codst = new CodeConditionStatement(); // 設置判斷條件 codst.Condition = eqexp; // 若是爲真 codst.TrueStatements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Console)), nameof(Console.WriteLine)), new CodePrimitiveExpression("這是偶數。"))); // 若是爲假 codst.FalseStatements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Console)), nameof(Console.WriteLine)), new CodePrimitiveExpression("這是奇數。"))); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); provider.GenerateCodeFromStatement(codst, Console.Out, null);
生成的代碼以下:ip
有時候,代碼只須要判斷條件成立並進行處理,而忽略條件不成立的情形,這時候 FalseStatements 中能夠不添加任何語句。以下面例子。rem
// 定義變量 CodeVariableDeclarationStatement varst = new CodeVariableDeclarationStatement(typeof(string), "str", new CodePrimitiveExpression("i-s-h-e-j-d-u")); // 訪問變量實例的屬性 CodePropertyReferenceExpression prpref = new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(varst.Name), nameof(string.Length)); // 生成判斷條件的表達式 CodeBinaryOperatorExpression codexp = new CodeBinaryOperatorExpression(); codexp.Operator = CodeBinaryOperatorType.GreaterThan; codexp.Left = prpref; codexp.Right = new CodePrimitiveExpression(5); // 分支語句 CodeConditionStatement codstatement = new CodeConditionStatement(); codstatement.Condition = codexp; // 條件成立時 CodeMethodInvokeExpression invmeth = new CodeMethodInvokeExpression(); invmeth.Method = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(typeof(Console)), nameof(Console.WriteLine)); invmeth.Parameters.Add(new CodePrimitiveExpression("字符串長度超出範圍。")); codstatement.TrueStatements.Add(invmeth); CodeDomProvider prd = CodeDomProvider.CreateProvider("cs"); prd.GenerateCodeFromStatement(varst, Console.Out, null); prd.GenerateCodeFromStatement(codstatement, Console.Out, null);
這個例子生成代碼爲:聲明一個字符串類型變量,並初始化。而後判斷其長度,並按條件執行輸出。生成的代碼以下。字符串
===========================================
循環語句的生成也不難,它由 CodeIterationStatement 類負責生成,其結構相似於 for 語句,由個要素組成:
一、循環條件的初始值。
二、判斷是否執行循環的條件。
三、對循環條件的更改。
下面經過示例,生成一個標準的for循環。
CodeIterationStatement its = new CodeIterationStatement(); // 初始化條件 its.InitStatement = new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression(0)); // 條件檢查 its.TestExpression = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.LessThan, new CodePrimitiveExpression(9)); // 每一輪循環後對條件的更改 its.IncrementStatement = new CodeAssignStatement(new CodeVariableReferenceExpression("i"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(2))); // 循環體 its.Statements.Add(new CodeCommentStatement("循環體代碼")); CodeDomProvider prd = CodeDomProvider.CreateProvider("vb"); prd.GenerateCodeFromStatement(its, Console.Out, null);
初始化一個變量i,條件是它小於9時發生循環,每次循環後會把條件加上2。
這時候會發現,生成的 VB 代碼是While循環。
而生成的C#代碼則是for循環。
你甭管它是什麼語法格式,只要邏輯上對了就行,這是生成代碼,不是寫代碼,不要患有強迫症。
想不想來個死循環,其實,死循環只要讓 TestExpression 永遠爲true,而且, IncrementStatement 不會更改條件的值就好了。好比這樣。
CodeIterationStatement itsmt = new CodeIterationStatement(); itsmt.InitStatement = new CodeVariableDeclarationStatement(typeof(bool), "n", new CodePrimitiveExpression(true)); itsmt.TestExpression = new CodeVariableReferenceExpression("n"); itsmt.IncrementStatement = new CodeAssignStatement(new CodeVariableReferenceExpression("n"), new CodePrimitiveExpression(true)); itsmt.Statements.Add(new CodeCommentStatement("無限做死……")); CodeDomProvider prd = CodeDomProvider.CreateProvider("cs"); prd.GenerateCodeFromStatement(itsmt, Console.Out, null);
初始化變量爲true,並每一輪循環後都讓它爲true。生成代碼以下:
其實,還能夠更簡單一點。
CodeIterationStatement itsmt = new CodeIterationStatement(); itsmt.InitStatement = new CodeSnippetStatement(""); itsmt.TestExpression = new CodePrimitiveExpression(true); itsmt.IncrementStatement = new CodeSnippetStatement(""); itsmt.Statements.Add(new CodeCommentStatement("無限做死……")); CodeDomProvider prd = CodeDomProvider.CreateProvider("cs"); prd.GenerateCodeFromStatement(itsmt, Console.Out, null);
老周在前面介紹過,CodeSnippetStatement 類能夠用原義文本生成代碼,這裏咱們把原義文本用空字符表示,就會生成空白語句。
因此,生成的C#代碼是這樣的:
生成的 VB 代碼是這樣的:
生成的C++代碼是這樣的:
好了,有關分支和循環的邏輯代碼的生成就介紹到此了,下一篇文章,我們就開始說說編譯代碼的事。