zoukankan      html  css  js  c++  java
  • 【.net 深呼吸】细说CodeDom(7):索引器

    在开始正题之前,先补充一点前面的内容。

    在方法中,如果要引用方法参数,前面的示例中,老周使用的是 CodeVariableReferenceExpression 类,它用于引用变量,也适用于引用方法参数。除了这个类,还可以使用 CodeArgumentReferenceExpression 类,这个类是专为方法参数引用而设计,其实用起来也和变量引用一样。请看看下面的例子。

                CodeMemberMethod m = new CodeMemberMethod();
                m.Name = "Test";
                // 输出参数
                CodeParameterDeclarationExpression p = new CodeParameterDeclarationExpression(typeof(int), "a");
                p.Direction = FieldDirection.Out;
                m.Parameters.Add(p);
                // 赋值语句
                CodeAssignStatement ass = new CodeAssignStatement();
                ass.Left = new CodeArgumentReferenceExpression(p.Name);
                ass.Right = new CodePrimitiveExpression(100000);
                m.Statements.Add(ass);
    
                CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");
                CodeGeneratorOptions opt = new CodeGeneratorOptions
                {
                    BracingStyle = "C"
                };
                provider.GenerateCodeFromMember(m, Console.Out, opt);

    Test 方法带有一个输出参数a,int类型,方法体中给参数a赋值。上面代码执行后,生成的代码如下图所示。

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

    好,进入主题,今天咱们来聊一聊“索引”这玩意儿。通常,使用索引的类型有:数组、List、哈希表/字典等。使用索引的类型成员有索引器。索引器可能不多见,其实跟属性很像。

    先来看看数组的初始化方法。初始化数组是一类表达式,主要用到 CodeArrayCreateExpression 类。

    看一个简单的例子。

                CodeArrayCreateExpression ce = new CodeArrayCreateExpression();
                ce.CreateType = new CodeTypeReference(typeof(string));
                ce.Size = 5;
    
                CodeDomProvider p = CodeDomProvider.CreateProvider("C#");
                p.GenerateCodeFromExpression(ce, Console.Out, null);

    CreateType 属性用来指定数组的类型,本例中类型为string,Size属性指定数组的大小。得到的代码如下图所示。

     由于不是所有语言都支持多维数组和嵌套数组,所以,目前来说,CodeDom并不能实例化多维数组。不过也没关系,毕竟N维数组和嵌套数组很少会用得上。

    有时候,在实例化数组对象的时候就顺便对元素进行初始化,可以将初始化元素的表达式添加到 Initializers 集合中。请看下面例子。

                CodeArrayCreateExpression arrce = new CodeArrayCreateExpression();
                arrce.CreateType = new CodeTypeReference(typeof(int));
                // 初始化元素
                arrce.Initializers.Add(new CodePrimitiveExpression(1));
                arrce.Initializers.Add(new CodePrimitiveExpression(3));
                arrce.Initializers.Add(new CodePrimitiveExpression(5));
                // 声明变量
                CodeVariableDeclarationStatement vd = new CodeVariableDeclarationStatement();
                vd.Name = "x";
                vd.Type = new CodeTypeReference(typeof(int[]));
                vd.InitExpression = arrce;

    最后使用 CodeVariableDeclarationStatement 产生一句完整的变量声明语句,初始化变量时就用CodeArrayCreateExpression表达式。

    生成的代码如下图所示。

    要访问某个数组变量的指定索引处的值,可以用 CodeArrayIndexerExpression 类。

                CodeArrayIndexerExpression aiexp = new CodeArrayIndexerExpression();
                aiexp.TargetObject = new CodeVariableReferenceExpression("x");
                aiexp.Indices.Add(new CodePrimitiveExpression(0));

    TargetObject属性用来设置对数组变量的引用,Indices集合用来添加索引引用表达式,数组的索引都是整数,所以,应当用以下表达式:

    new CodePrimitiveExpression(<整数值>)

    上面示例生成的代码如下图所示。

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

    下面咱们看看索引器。

    访问索引器最典型的一个应用是字典。下面例子将生成三个语句,其中,第一句是声明被初始化一个字典变量,第二句和第三句都是向字典变量添加元素。

                // 声明并初始化字典变量
                CodeVariableDeclarationStatement vd = new CodeVariableDeclarationStatement();
                vd.Type = new CodeTypeReference(typeof(Dictionary<string, string>));
                vd.Name = "dic";
                vd.InitExpression = new CodeObjectCreateExpression(typeof(Dictionary<string, string>));
    
                // 给字典对象添加元素
                // 左边:索引引用
                // 右边:值
                CodeAssignStatement ass = new CodeAssignStatement();
                ass.Left = new CodeIndexerExpression(new CodeVariableReferenceExpression(vd.Name), new CodePrimitiveExpression("a"));
                ass.Right = new CodePrimitiveExpression("cake");
                CodeAssignStatement ass1 = new CodeAssignStatement();
                ass1.Left = new CodeIndexerExpression(new CodeVariableReferenceExpression(vd.Name), new CodePrimitiveExpression("b"));
                ass1.Right = new CodePrimitiveExpression("bird");
    
                CodeDomProvider prd = CodeDomProvider.CreateProvider("cs");
                prd.GenerateCodeFromStatement(vd, Console.Out, null);
                prd.GenerateCodeFromStatement(ass, Console.Out, null);
                prd.GenerateCodeFromStatement(ass1, Console.Out, null);

    引用某个实例的索引器,应使用 CodeIndexerExpression 类。TargetObject属性用来指定要引用的对象,通常是变量引用,Indices属性是索引集合,用来指定要访问的索引。这些属性的值可以直接向CodeIndexerExpression类的构造函数传递。

    本例生成的代码如下。

    System.Collections.Generic.Dictionary<string, string> dic = new System.Collections.Generic.Dictionary<string, string>();
    dic["a"] = "cake";
    dic["b"] = "bird";

    如果要给自定义的类型声明索引器,要用 CodeMemberProperty 类,因为索引器与属性相似。还是用例子说话吧。

                CodeTypeDeclaration td = new CodeTypeDeclaration("Sample");
                td.Attributes = MemberAttributes.Public;
                // 索引器
                CodeMemberProperty mb = new CodeMemberProperty();
                mb.Type = new CodeTypeReference(typeof(string));
                mb.Name = "item";
                mb.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                // 索引参数
                mb.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "k"));
                td.Members.Add(mb);
    
                CodeDomProvider provider = CodeDomProvider.CreateProvider("cs");
                provider.GenerateCodeFromType(td, Console.Out, null);

    这里有个地方要注意,就是索引器成员的名字,为了兼容各种语言,较合适的做法是把它命名为“item”或“Item”(不分大小写),这样一来,生成C#代码时,就能够生成 this[int k] 这样的语法,只有这样的语法才能被认为是索引器。

    生成的代码如下图所示。

    好了,今天对索引器代码生成相关的内容就扯到这里了,下一篇文章,老周就继续和大家聊聊条件语句与循环语句。

    开饭了……

  • 相关阅读:
    4、Cocos2dx 3.0三,找一个小游戏开发Hello World 分析
    Android Bluetooth开发
    详细解析BluetoothAdapter的详细api
    Android 蓝牙( Bluetooth)耳机连接分析及实现
    [Andriod官方API指南]连接之蓝牙
    Android蓝牙A2dp profile的使用
    Android中文API(129) —— AudioManager
    Android中的Audio播放:控制Audio输出通道切换
    JAVA ANDROID SOCKET通信检测(SERVER)连接是否断开
    Android Xfermode 实战 实现圆形、圆角图片
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6244408.html
Copyright © 2011-2022 走看看