zoukankan      html  css  js  c++  java
  • 动态生成与编译(六)――测试一下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生成的那个类,及后面用来测试它的代码正常的工作。

  • 相关阅读:
    LOJ#6501. 「雅礼集训 2018 Day4」Cube 题解
    LOJ#6510. 「雅礼集训 2018 Day8」A 题解
    LOJ#6513. 「雅礼集训 2018 Day10」足球大战 题解
    LOJ#6507. 「雅礼集训 2018 Day7」A 题解
    LOJ#6038. 「雅礼集训 2017 Day5」远行 题解
    Luogu P4208 [JSOI2008]最小生成树计数
    CodeForces 916D Jamie and To-do List
    CodeForces 573B Bear and Blocks
    CodeForces 460C Present
    CodeForces 786B Legacy
  • 原文地址:https://www.cnblogs.com/lichdr/p/60715.html
Copyright © 2011-2022 走看看