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

在方法中,如果要引用方法参数,前面的示例中,老周使用的是 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();
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 = ; 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());
arrce.Initializers.Add(new CodePrimitiveExpression());
arrce.Initializers.Add(new CodePrimitiveExpression());
// 声明变量
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());

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] 这样的语法,只有这样的语法才能被认为是索引器。

生成的代码如下图所示。

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

开饭了……

【.net 深呼吸】细说CodeDom(7):索引器的更多相关文章

  1. 【.net 深呼吸】细说CodeDom(1):结构大观

    CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧.DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了.如果你从来没接触过 CodeDom,你大概 ...

  2. C# 索引器,实现IEnumerable接口的GetEnumerator()方法

    当自定义类需要实现索引时,可以在类中实现索引器. 用Table作为例子,Table由多个Row组成,Row由多个Cell组成, 我们需要实现自定义的table[0],row[0] 索引器定义格式为 [ ...

  3. C#基础回顾(三)—索引器、委托、反射

    一.前言                                                                                       ------人生路 ...

  4. C#索引器

    索引器允许类或者结构的实例按照与数组相同的方式进行索引取值,索引器与属性类似,不同的是索引器的访问是带参的. 索引器和数组比较: (1)索引器的索引值(Index)类型不受限制 (2)索引器允许重载 ...

  5. C#之索引器

    实际中不使用这个东西,只做了解 using System; using System.Collections.Generic; using System.Linq; using System.Text ...

  6. C#属性-索引器-里氏替换-多态-虚方法-抽象-接口-泛型-

    1.属性 //属性的2种写法 public class person { private string _name; public string Name { get { return _name; ...

  7. 《精通C#》索引器与重载操作符(11.1-11.2)

    1.索引器方法结构大致为<modifier><return type> this [argument list],它可以在接口中定义: 在为接口声明索引器的时候,记住声明只是表 ...

  8. 描述一下C#中索引器的实现过程,是否只能根据数字进行索引?

    不是.可以用任意类型. 索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了 ...

  9. C# 索引器使用总结

    1.索引器(Indexer): 索引器允许类或者结构的实例按照与数组相同的方式进行索引.索引器类似于属性,不同之处在于他们的访问采用参数. 最简单的索引器的使用 /// <summary> ...

随机推荐

  1. 用php做注册审核

    做注册审核就像前面讲的注册登录一样,也是要连接数据库 首先在数据库内要做这样一张表: 表名为users表 里面的列名分别为用户名,密码,姓名,性别,生日,账户的状态,照片 然后就可以写代码了,要注册的 ...

  2. Unity 序列化 总结

    查找了 Script Serialization http://docs.unity3d.com/Manual/script-Serialization.html 自定义序列化及例子: http:// ...

  3. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  4. 【开源】.net 分布式架构之监控平台

    开源地址:http://git.oschina.net/chejiangyi/Dyd.BaseService.Monitor .net 简单监控平台,用于集群的性能监控,应用耗时监控管理,统一日志管理 ...

  5. zookeeper源码分析之二客户端启动

    ZooKeeper Client Library提供了丰富直观的API供用户程序使用,下面是一些常用的API: create(path, data, flags): 创建一个ZNode, path是其 ...

  6. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  7. 使用HttpClient的优解

    新工作入职不满半周,目前仍然还在交接工作,适应环境当中,笔者不得不说看别人的源码实在是令人痛苦.所幸今天终于将大部分工作流畅地看了一遍,接下来就是熟悉框架技术的阶段了. 也正是在看源码的过程当中,有一 ...

  8. javascript有用小功能总结(未完待续)

    1)javascript让页面标题滚动效果 代码如下: <title>您好,欢迎访问我的博客</title> <script type="text/javasc ...

  9. 【从零开始学BPM,Day4】业务集成

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第四天课程] 1.课程概要 Step 1 软件下载:H3 BP ...

  10. SAP自定义权限对象

    SAP系统自带了很多的权限对象,每一个运行画面都有非常多的权限用到.不过标准的权限对象并不一定适合于用在客户自己开发的程序里面,所以每个ABAPer都应该会自己开发一套权限对象,并引用在程序代码里面. ...