Net有道

紫冠道人的求道历程

导航

动态生成与编译(六)――测试一下CodeDOM生成的类

 

这么简单的一个类,其实直接让它生成类代码看一下也就知道行不行了。但既然做就做到底,把测试用的代码也一并用CodeDOM来生成算了,而且CodeDOM里还有几个类也要随便说一下。

先看生成后的代码(直接在原namespace里新做了一个类):

public class TestClass {

       

        public static void Main() {

            DemoClass a = new DemoClass();

            DemoClass b = new DemoClass(123);

            Console.WriteLine("MyConst = {0}", DemoClass.MyConst);

            Console.WriteLine("a.MyProperty = {0}", a.MyProperty);

            Console.WriteLine("b.MyProperty = {0}", b.MyProperty);

            a.MyMethod();

            // 附加委托

            a.MyEvent += new myEventHandler(TestClass.MyHandler);

            a.MyMethod();

            // 移除委托

            a.MyEvent -= new myEventHandler(TestClass.MyHandler);

            a.MyMethod();

            a[5] = (a[3] = 11);

            for (int i = 0; (i < 10); i = (i + 1)) {

                Console.WriteLine("a[{0}] = {1}", i, a[i]);

            }

            Console.Read();

        }

       

        static void MyHandler(object sender, myEventArgs e) {

            Console.WriteLine(e.Dt.ToString());

        }

    }

 

现在虽然看CodeDOM程序时虽能在脑海里浮现生成的相应代码了,但CodeDOM程序还写得不熟,如果不对着生成的代码来写CodeDOM程序还是有点累。现在一般都要先写好目标代码的大致形状,再反过来写CodeDOM程序,现在也照上面生成的代码来分析要写的CodeDOM程序。

CodeTypeDeclaration TestClass = new CodeTypeDeclaration("TestClass");

CodeEntryPointMethod Start = new CodeEntryPointMethod();

开始这两句总归是少了的,下面两句声明变量ab的只讲一句(第二句稍复杂,就讲它了),变量声明的以前讲到过了。如果不初始化变量倒是简单:

                CodeVariableDeclarationStatement classb = new CodeVariableDeclarationStatement("DemoClass","b")

OK,后面那个new DemoClass(123)一加就烦了,要设置classbInitExpression(或者在构造函数里传第三个参数,效果一样的)。一看New什么什么的,下面要用上类的构造函数了,在CodeDOM里创建一个类的新实例的表达式用

public CodeObjectCreateExpression(
   string createType,
   params CodeExpression[] parameters
);

第一个参数是要创建的类型,第二个参数是构造函数的参数,当然没有参数就省略了,上面的CodeDOM程序加上

classb.InitExpression = new CodeObjectCreateExpression("DemoClass",new odePrimitiveExpression(123))

后就完成第二句变量b的声明了。

 

下面三句输出控制台的语句就是方法调用,这个是很熟的了,一开始就用过的,当然是用CodeMethodInvokeExpression了。它的参数的DemoClass.MyConst a.MyProperty这两个分别就是类的字段、属性依次用CodeFieldReferenceExpressionCodePropertyReferenceExpression也很简单的。只看一下第二句的写法:

new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"),"WriteLine",

new CodeExpression[] {new CodePrimitiveExpression("a.MyProperty = {0}"),new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("a"),"MyProperty")});

 

(我喜欢这种长长的写法,不用去声明一串的变量,这样一眼就能看出来产生的代码是什么。只要输的时候左括号、右括号先对好就不太会出错)

 

接下来几句是看事件的效果的,先调一下MyMethod,加委托后再调一次,移除委托后最后调一次。主要是附加与移除委托的这两句。

先看new myEventHandler(TestClass.MyHandler)这一句是如何产生的,又是一个new,不过它不是类实例的创建,当然用CodeObjectCreateExpression来写,最后的代码效果是一样的,不过还是不要那样写的好。创建委托用

public CodeDelegateCreateExpression(
   CodeTypeReference delegateType,
   CodeExpression targetObject,
   string methodName

);

所以CodeDelegateCreateExpression delecra = new CodeDelegateCreateExpression(。。。略);

后面的委托new好了,下面就是加上去的事:

CodeAttachEventStatement attevent = new CodeAttachEventStatement(

new CodeVariableReferenceExpression("a"),"MyEvent",delecra);

是附加,那

CodeRemoveEventStatement removevent = new CodeRemoveEventStatement(

new CodeVariableReferenceExpression("a"),"MyEvent",delecra);

就是移除了。

 

最后看一下类的索引器属性。a[5] = (a[3] = 11);这一句连续赋值的,先看a[5]是如何来的,这实际就是数组里的东西是如何取的问题啦,CodeDOM有一个CodeArrayIndexerExpression刚好可以派上用场。new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("a"),new CodePrimitiveExpression(5))就会产生a[5],很明显前一个参数是索引器的对象,后一个参数是具体的索引数。

下面的连续赋值, CodeDOM生成a[5]=a[3]=11)这样看起来还是比较的清楚。它就是一个CodeAssignStatement,左项是a[5],而右项(a[3]=11)就是一个运算表达式CodeBinaryOperatorExpression,只不过它的运算符是赋值运算符而已。其实生成(a[5]=a[3])=11也是一样的。

不过上面的这两种写法要写的CodeDOM代码复杂得要命,还不如分成两句赋值语句写来得省事。

后面的一个循环没什么,最简单基本的东西,在(三)里提过了,略过。

 

下面那个供委托用的“MyHandler”方法只有一句方法调用,也没什么新东西。

 

用上面的CodeDOM程序生成的代码文件编译产生EXE文件,双击执行,在控制台输出如下:

Instance constructor1

Instance constructor2

MyConst = 12

a.MyProperty = 0

b.MyProperty = 123

DemoClass.MyMethod

DemoClass.MyMethod

Invokes MyEvent

2004-11-04 21:20:50   -------这里当然与程序执行时间有关

DemoClass.MyMethod

a[0] = 0

a[1] = 0

a[2] = 0

a[3] = 11

a[4] = 0

a[5] = 11

a[6] = 0

a[7] = 0

a[8] = 0

a[9] = 0

 

看来CodeDOM生成的那个类,及后面用来测试它的代码正常的工作。

posted on 2004-11-05 12:01  lichdr  阅读(4005)  评论(1编辑  收藏  举报