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

在方法中,如果要引用方法参数,前面的示例中,老周使用的是 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. CSS3 border-radius边框圆角

    在CSS3中提供了对边框进行圆角设定的支持,可对边框1~4个角进行圆角样式设置. 目录 1. 介绍 2. value值的格式和类型 3. border-radius 1~4个参数说明 4. 在线示例 ...

  2. 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)

    建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...

  3. 【资源】.Net 入门@提高 - 逆天的高薪之路!

     入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~    官方学习计划 http://www.cnblogs.com/dunitian/p/5667901.html ----- ...

  4. jQuery学习之路(3)- 事件

    ▓▓▓▓▓▓ 大致介绍 jQuery增加了并扩展了基本的事件处理机制,不但提供了更加优雅的事件处理语法,而且极大地增强了事件处理能力 ▓▓▓▓▓▓ jQuery中的事件 ▓▓▓▓▓▓ 加载DOM 在j ...

  5. Hawk 4.7 单步调试

    单步调试的意义 已经编写的工作流,可能会因为某些外界环境的变化而出错,此时需要排除错误,我们可以使用单步调试. 单步调试的本质,相当于只使用前n个模块,这样就能看到每个步骤下,流的改变. 例子 还是上 ...

  6. [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化

    KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...

  7. 如何用Java类配置Spring MVC(不通过web.xml和XML方式)

    DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servl ...

  8. maven依赖查询地址

    http://search.maven.org/#search%7Cga%7C1%7C

  9. 手动导入swift三方danielgindi/Charts到OC工程中教程

    1.到github网址上下载zip压缩包https://github.com/danielgindi/Charts 2.然后将解压后的文件夹整个拖到自己的工程文件夹下(很多教程只让拖xcodeproj ...

  10. 实现php连接memcached

    准备工作: 实现lnmp环境 给php添加模块,so库 下载扩展包:memcache-2.2.5.tgz wget http://pecl.php.net/get/memcache-2.2.5.tgz