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

在方法中,如果要引用方法参数,前面的示例中,老周使用的是 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. 如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

    阅读目录 前言 如何在一个项目中实现多个上下文的业务 售价上下文与购买上下文的集成 结语 一.前言 前几篇已经实现了一个最简单的购买过程,这次开始往这个过程中增加一些东西.比如促销.会员价等,在我们的 ...

  2. Logstash实践: 分布式系统的日志监控

    文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...

  3. 使用 JavaScript 和 canvas 做精确的像素碰撞检测

    原文地址:Pixel accurate collision detection with Javascript and Canvas 译者:nzbin 我正在开发一个需要再次使用碰撞检测的游戏.我通常 ...

  4. Windows 常用运行库下载 (DirectX、VC++、.Net Framework等)

    经常听到有朋友抱怨他的电脑运行软件或者游戏时提示缺少什么 d3dx9_xx.dll 或 msvcp71.dll.msvcr71.dll又或者是 .Net Framework 初始化之类的错误而无法正常 ...

  5. 如何利用tcpdump对mysql进行抓包操作

    命令如下: tcpdump -s -l -w - dst -i eno16777736 |strings 其中-i指定监听的网络接口,在RHEL 7下,网络接口名不再是之前的eth0,而是 eno16 ...

  6. System.Guid ToString五中格式

    参考:https://msdn.microsoft.com/en-us/library/97af8hh4.aspx 测试代码: using System; using System.Collectio ...

  7. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  8. 如何搭建git服务器

    一.前言 现在越来越多的公司用git进行版本控制,不过git是默认是开源的,如果私有的话是需要付费的,如果不想付费自己可以搭建一个git服务器用来版本控制. 二.服务器端操作 1.安装git sudo ...

  9. Linux:将rhel yum 切换到centos yum

    Red Hat Enterprise Linux Server(RHEL) yum安装软件时This system is not registered with RHN. RHN support wi ...

  10. 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)

    今天给大家道个歉,没有及时更新MongoDB快速入门的下篇,最近有点小忙,在此向博友们致歉.下面我将简单地说一下mongdb的一些基本命令以及我们日常开发过程中的一些问题.mongodb可以为我们提供 ...