CodeDom系列二

---程序基本结构--符号三角形问题

昨天一个同学叫我帮编写一个符号三角形的c代码,今天就把它改写成用CodeDom生成的c#代码。

    符号三角形:在一组字符串里(只有用空格分割的+或者-组成的字符串),在每次的相邻的两个符号比较,如果相同就在中间空格插入+,否则就插入-。一直运行到字符串里只有一个+或者-时停止,输出的字符串为符号三角形。

由于是CodeDom些列,所以先介绍几个CodeDom表达式:

1:CodeConditionStatement:判断语句即是if(condition){} else{},看最全的那个构造函数:

public CodeConditionStatement(CodeExpression condition,//条件CodeStatement[] trueStatements,//为true的语句体CodeStatement[] falseStatements//为false语句体)
2:CodeIterationStatement():表示 for 语句或语句块内的循环(使用测试表达式作为继续循环的条件):
在codedom中没有提高while和dowhile但是For已经够用的
public CodeIterationStatement(CodeStatement initStatement,//for初始化CodeExpression testExpression,//条件表达式CodeStatement incrementStatement,//for变化体,增或减CodeStatement[] statements//循环体)
3:CodeBinaryOperatorExpression:表示一个表达式,该表达式包含在两个表达式间进行的二进制运算,
public CodeBinaryOperatorExpression(CodeExpression left,//表达式左边CodeBinaryOperatorType op,//操作符CodeExpression right//表达式右边)
4:CodeArrayIndexerExpression:表示对数组的索引的引用:
public CodeArrayIndexerExpression(CodeExpression targetObject,//数组对象CodeExpression[] indices//下标)
其他参见CodeDOM 快速参考:msdn.microsoft.com/zh-cn/library/f1dfsbhc(VS.80).aspx
code:
04 public CodeNamespace CreateNameSpace()
05 {
06 public CodeNamespace CreateNameSpace()
07 {
08 //Test
09 CodeMemberMethod test = new CodeMemberMethod();
10 test.Name = "Test";
11 test.Attributes = MemberAttributes.Public | MemberAttributes.Final;
12 test.Statements.Add(new CodeVariableDeclarationStatement(typeof(char[]), "ch",
4 new CodeMethodInvokeExpression(new CodePrimitiveExpression("+ - + - + + - -"), "ToCharArray",
4 new CodeExpression[] { })));
5 test.Statements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression
4 (new CodeThisReferenceExpression(), "FuHaoSanJiao"), new CodeExpression[] { new CodeVariableReferenceExpression("ch"),
4 new CodePrimitiveExpression(0) }));
5 test.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"), "Read"));
6 //FuHaoSanJiao
7 CodeMemberMethod fuHaoSanJiao = new CodeMemberMethod();
8 fuHaoSanJiao.Name = "FuHaoSanJiao";
9 fuHaoSanJiao.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(char[])),
4 "ch"));
5 fuHaoSanJiao.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "start"));
6 fuHaoSanJiao.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"),
4 "WriteLine", new CodeExpression[] { new CodeObjectCreateExpression(typeof(string), new CodeArgumentReferenceExpression("ch")) }));
5 fuHaoSanJiao.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(
4 new CodeArgumentReferenceExpression("start"), CodeBinaryOperatorType.GreaterThanOrEqual,
5 (new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(
4 new CodeArgumentReferenceExpression("ch"),"Length"),
5 CodeBinaryOperatorType.Divide ,new CodePrimitiveExpression(2)))),
6 new CodeMethodReturnStatement()));
7 CodeBinaryOperatorExpression condition=new CodeBinaryOperatorExpression(
04 new CodeVariableReferenceExpression("i"),
05 CodeBinaryOperatorType.LessThan,
06 new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression("ch"),"Length"),
07 CodeBinaryOperatorType.Subtract ,new CodeArgumentReferenceExpression("start")), CodeBinaryOperatorType.Subtract,
08 new CodePrimitiveExpression(1)));//for 条件
09 CodeConditionStatement iterationBody=new CodeConditionStatement(new CodeBinaryOperatorExpression(
10 new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("ch"),
4 new CodeVariableReferenceExpression("i")),
5 CodeBinaryOperatorType.IdentityEquality, new CodeArrayIndexerExpression(
4 new CodeArgumentReferenceExpression("ch"),
5 new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"),
4 CodeBinaryOperatorType.Add,new CodePrimitiveExpression(2)))),
5 new CodeAssignStatement(
6 new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("ch"),
4 new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add,
4 new CodePrimitiveExpression(1))),
5 new CodePrimitiveExpression('+')));
6 iterationBody.FalseStatements.Add(new CodeAssignStatement(
7 new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("ch"),
4 new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add,
4 new CodePrimitiveExpression(1))),
5 new CodePrimitiveExpression('-')));
6 CodeAssignStatement iteerationbody2 = new CodeAssignStatement(new CodeArrayIndexerExpression(
4 new CodeArgumentReferenceExpression("ch"), new CodeVariableReferenceExpression("i")),
5 new CodePrimitiveExpression(' '));
6 fuHaoSanJiao.Statements.Add(new CodeIterationStatement(new CodeVariableDeclarationStatement(typeof(int),
4 "i", new CodeArgumentReferenceExpression("start")), condition,
5 new CodeAssignStatement(new CodeVariableReferenceExpression("i"),new CodeBinaryOperatorExpression(
4 new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add,
5 new CodePrimitiveExpression(2))), new CodeStatement[] { iterationBody, iteerationbody2 }));
6 // ch[ch.Length - start - 1] = ' ';
7 fuHaoSanJiao.Statements.Add(new CodeAssignStatement(
8 new CodeArrayIndexerExpression(new CodeArgumentReferenceExpression("ch"),
4 new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(
4 new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression("ch"), "Length"),
5 CodeBinaryOperatorType.Subtract ,new CodeArgumentReferenceExpression("start")),
4 CodeBinaryOperatorType.Subtract,
5 new CodePrimitiveExpression(1))),new CodePrimitiveExpression(' ')));
6 //  FuHaoSanJiao(ch, start + 1);
7 fuHaoSanJiao.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
4 "FuHaoSanJiao",new CodeArgumentReferenceExpression("ch")        ,
5 new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("start"),
04 CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))));
05 CodeTypeDeclaration codeDomDemo2 = new CodeTypeDeclaration("CodeDomDemo2");
06 codeDomDemo2.Members.Add(test);
07 codeDomDemo2.Members.Add(fuHaoSanJiao);
08 codeDomDemo2.Attributes = MemberAttributes.Public;
09 codeDomDemo2.Comments.Add(new CodeCommentStatement("this code is from CodeDom!"));
10 //codeDomDemo2.Members.AddRange();
11 CodeNamespace nspace = new CodeNamespace("CodeDomDemo2");
12 nspace.Imports.Add(new CodeNamespaceImport("System"));
13 nspace.Types.Add(codeDomDemo2);
14 return nspace;
15 }
16 }
17 }

输出代码为 :

04 namespace CodeDomDemo2
05 {
06 using System;
07 // this code is from CodeDom!
08 public class CodeDomDemo2
09 {
10 public void Test()
11 {
12 char[] ch = "+ - + - + + - -".ToCharArray();
13 this.FuHaoSanJiao(ch, 0);
14 System.Console.Read();
15 }
16 private void FuHaoSanJiao(char[] ch, int start)
17 {
18 System.Console.WriteLine(new string(ch));
19 if ((start
20 >= (ch.Length / 2)))
21 {
22 return;
23 }
24 for (int i = start; (i
25 < ((ch.Length - start)
26 - 1)); i = (i + 2))
27 {
28 if ((ch[i] == ch[(i + 2)]))
29 {
30 ch[(i + 1)] = '+';
31 } else
32 {
33 ch[(i + 1)] = '-';
34 }
35 ch[i] = ' ';
36 }
37 ch[((ch.Length - start)
38 - 1)] = ' ';
39 this.FuHaoSanJiao(ch, (start + 1));
40 }
41 }
42 }

代码下载Demo1,Demo2

事件(event)定义和反射调用

    CodeDom提供了对事件的支持,以及我们可以用反射机制对CodeDom生成的事件进行注册,以及调用。本节程序很简单,先贴上我将用CodeDom生成的代码:

04 namespace CodeDomDemo3
05 {
06 using System;
07 public class CodeDomDemo3
08 {
09 public event System.EventHandler MyEvent;
10 protected virtual void OnHandle(System.EventArgs e)
11 {
12 if ((this.MyEvent != null))
13 {
14 this.MyEvent(this, e);
15 }
16 }
17 public void CallEvent()
18 {
19 this.OnHandle(EventArgs.Empty);
20 }
21 }
22 }

代码很简单哦,主要是看CodeDom的事件定义机制和反射调用CodeDom编译的类型方法事件。

CodeDom代码为:

04 using System;
05 using System.Collections.Generic;
06 using System.Linq;
07 using System.Text;
08 using System.CodeDom;
09 namespace CodeDomDemo1
10 {
11 public class CodeDomDemo3
12 {
13 public CodeNamespace CreateCodeNamespcae()
14 {
15 CodeNamespace nspcae = new CodeNamespace("CodeDomDemo3");
16 nspcae.Imports.Add(new CodeNamespaceImport("System"));
17 nspcae.Types.Add(CrateClassType());
18 return nspcae;
19 }
20 public CodeTypeDeclaration CrateClassType()
21 {
22 //field event
23 CodeMemberEvent myevent = new CodeMemberEvent();
24 myevent.Attributes = MemberAttributes.Public;
25 myevent.Type = new CodeTypeReference(typeof(EventHandler));
26 myevent.Name = "MyEvent";
27 // event method OnHandle;
28 CodeMemberMethod method = new CodeMemberMethod();
29 method.Name = "OnHandle";
30 method.Attributes = MemberAttributes.Family;
31 method.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(EventArgs)), "e"));
32 method.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeEventReferenceExpression(
4 new CodeThisReferenceExpression(),"MyEvent"),
5 CodeBinaryOperatorType.IdentityInequality,new CodePrimitiveExpression(null)),
6 new CodeExpressionStatement(new CodeDelegateInvokeExpression(new CodeEventReferenceExpression(
04 new CodeThisReferenceExpression(),
05 "MyEvent"), new CodeExpression[] { new CodeThisReferenceExpression(), new CodeArgumentReferenceExpression("e"),
06 }))));
07 CodeMemberMethod callEvent = new CodeMemberMethod();
08 callEvent.Name = "CallEvent";
09 callEvent.Attributes = MemberAttributes.Public | MemberAttributes.Final;
10 callEvent.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "OnHandle", new CodeExpression[]
04 {new CodePropertyReferenceExpression(new CodeTypeReferenceExpression("EventArgs"),"Empty") }));
05 CodeTypeDeclaration myclass = new CodeTypeDeclaration("CodeDomDemo3");
06 myclass.Attributes = MemberAttributes.Public;
07 myclass.Members.AddRange(new CodeTypeMember[] { myevent, method, callEvent });
08 return myclass;
09 }
10 }
11 }
4 1:主要注意委托的调用:
public CodeDelegateInvokeExpression(CodeExpression targetObject,//事件的引用CodeExpression[] parameters//参数)
2:事件的添加(+=):
public CodeAttachEventStatement(CodeExpression targetObject,//目标对象string eventName,//事件名CodeExpression listener//监听者)
3:事件的移除(-=):
public CodeRemoveEventStatement(CodeExpression targetObject,//目标对象string eventName,//事件名CodeExpression listener//监听者)
   利用反射调用事件代码:
4 Type t = result.CompiledAssembly.GetType("CodeDomDemo3.CodeDomDemo3");//获取类型
5 object obj= Activator.CreateInstance(t);//创建实例
6 t.GetEvent("MyEvent").AddEventHandler(obj, new EventHandler(pro.CallEvent));//添加事件
7 t.GetMethod("CallEvent").Invoke(obj, null);//触发事件

本示例代码下载:CodeDomDemo3

你可能感兴趣的:(code)