首页 技术 正文
技术 2022年11月7日
0 收藏 548 点赞 632 浏览 4819 个字

有人会问,为啥 CodeDom 不会生成 switch 语句,为啥没生成 while 语句之类。要注意,CodeDom只关心代码逻辑,而不是语法,语法是给写代码的人用的。如果用.net的“反编译”工具的朋友会知道,你用while语句写了一段代码,然后编译生成程序集,再用工具把代码“反”出来,此时你会发现,你原来写的是while语句,但出来的是for语句,道理是一样的,“反编译”工具只关心代码的执行逻辑,而不是语法。所以,你自然无法用 CodeDom 来生成var关键字来声明变量,也无法生成用 Lambda 表达式表示的方法,也不能生成仅有get和set的属性定义语法。

因此,大家不要把语法和逻辑搞混。

先来介绍一下分支,分支语句类似 if 语句,由 CodeConditionStatement 类表示,它需要三个要素:

1、条件,用于判断给定的表达式是否为true。

2、当条件成立时所执行的代码。

3、当条件不成立时所执行的代码。

下面举个例子,让某数除以2,并取模(即取余),如果结果为0,即为偶数,否则为奇数。代码如下。

            // 取模运算
CodeBinaryOperatorExpression modexp = new CodeBinaryOperatorExpression();
modexp.Operator = CodeBinaryOperatorType.Modulus;
modexp.Left = new CodePrimitiveExpression();
modexp.Right = new CodePrimitiveExpression();
// 相等运算
CodeBinaryOperatorExpression eqexp = new CodeBinaryOperatorExpression();
eqexp.Operator = CodeBinaryOperatorType.IdentityEquality;
eqexp.Left = modexp;
eqexp.Right = new CodePrimitiveExpression();
// 分支语句
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);

生成的代码如下:

【.net 深呼吸】细说CodeDom(8):分支与循环

有时候,代码只需要判断条件成立并进行处理,而忽略条件不成立的情形,这时候 FalseStatements 中可以不添加任何语句。如下面例子。

            // 定义变量
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();
// 分支语句
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);

这个例子生成代码为:声明一个字符串类型变量,并初始化。然后判断其长度,并按条件执行输出。生成的代码如下。

【.net 深呼吸】细说CodeDom(8):分支与循环

===========================================

循环语句的生成也不难,它由 CodeIterationStatement 类负责生成,其结构类似于 for 语句,由个要素组成:

1、循环条件的初始值。

2、判断是否执行循环的条件。

3、对循环条件的更改。

下面通过示例,生成一个标准的for循环。

            CodeIterationStatement its = new CodeIterationStatement();
// 初始化条件
its.InitStatement = new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression());
// 条件检查
its.TestExpression = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.LessThan, new CodePrimitiveExpression());
// 每一轮循环后对条件的更改
its.IncrementStatement = new CodeAssignStatement(new CodeVariableReferenceExpression("i"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression()));
// 循环体
its.Statements.Add(new CodeCommentStatement("循环体代码")); CodeDomProvider prd = CodeDomProvider.CreateProvider("vb");
prd.GenerateCodeFromStatement(its, Console.Out, null);

初始化一个变量i,条件是它小于9时发生循环,每次循环后会把条件加上2。

这时候会发现,生成的 VB 代码是While循环。

【.net 深呼吸】细说CodeDom(8):分支与循环

而生成的C#代码则是for循环。

【.net 深呼吸】细说CodeDom(8):分支与循环

你甭管它是什么语法格式,只要逻辑上对了就行,这是生成代码,不是写代码,不要患有强迫症。

想不想来个死循环,其实,死循环只要让 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。生成代码如下:

【.net 深呼吸】细说CodeDom(8):分支与循环

其实,还可以更简单一点。

            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#代码是这样的:

【.net 深呼吸】细说CodeDom(8):分支与循环

生成的 VB 代码是这样的:

【.net 深呼吸】细说CodeDom(8):分支与循环

生成的C++代码是这样的:

【.net 深呼吸】细说CodeDom(8):分支与循环

好了,有关分支和循环的逻辑代码的生成就介绍到此了,下一篇文章,咱们就开始说说编译代码的事。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,489
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,904
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,490
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,290