【.net 深呼吸】细说CodeDom(6):方法参数
本文老周就给大伙伴们介绍一下方法参数代码的生成。
在开始之前,先补充一下上一篇烂文的内容。在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作,后来发现是可以的。不过啊,MemberAttributes 枚举有些情况下不那么好弄,最典型的就是要生成抽象类的时候,反正老周试了很久,用MemberAttributes枚举不能顺利生成抽象类。
这时候,老周想到了 TypeAttributes,然后就试了一下。
CodeTypeDeclaration t = new CodeTypeDeclaration("MyClass"); t.TypeAttributes = System.Reflection.TypeAttributes.Abstract; CodeMemberProperty pry = new CodeMemberProperty(); pry.Name = "A"; pry.Attributes = MemberAttributes.Abstract | MemberAttributes.Public; pry.Type = new CodeTypeReference(typeof(string)); t.Members.Add(pry); CodeDomProvider p = CodeDomProvider.CreateProvider("cs"); p.GenerateCodeFromType(t, Console.Out, null);
把 TypeAttributes 属性设置为 Abstract ,就可以将类标识为抽象类。而抽象成员则可以将 Attributes 属性直接指定为抽象成员,比如上面例子中的A属性。
然后生成的代码如下图所示。
下面进入本文的要点——生成方法参数。
老周的习惯是,示例学习效率高。所以,我不多说理论的东西,来看例子。
CodeMemberMethod m = new CodeMemberMethod(); m.Name = "SetData"; m.Attributes = MemberAttributes.Public | MemberAttributes.Final; // 参数 CodeParameterDeclarationExpression p1 = new CodeParameterDeclarationExpression(); p1.Name = "name"; p1.Type = new CodeTypeReference(typeof(string)); m.Parameters.Add(p1); CodeParameterDeclarationExpression p2 = new CodeParameterDeclarationExpression(); p2.Name = "city"; p2.Type = new CodeTypeReference(typeof(string)); m.Parameters.Add(p2); CodeParameterDeclarationExpression p3 = new CodeParameterDeclarationExpression(); p3.Name = "phone"; p3.Type = new CodeTypeReference(typeof(int)); m.Parameters.Add(p3); CodeCommentStatement cm = new CodeCommentStatement("方法体"); m.Statements.Add(cm); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); provider.GenerateCodeFromMember(m, Console.Out, null);
别看这代码貌似有点长,其实就是声明一个方法,然后添加三个参数。参数的声明属于表达式,因此用到CodeParameterDeclarationExpression类,Type属性设置参数的类型。
示例代码中,CodeCommentStatement表示方法体中包含注释。
生成的方法如下图所示。
默认情况下,参数为输入参数,我们知道,还有两种方法参数——输出参数、引用传参。
CodeParameterDeclarationExpression 公开 Direction 属性,专门用于设置参数的方向,输入参数是默认值,因此可以不显式赋值,另外两个值就是Ref和Out。
下面代码将生成一个带有 out 参数的方法。
CodeMemberMethod m3 = new CodeMemberMethod(); m3.Name = "MakeKey"; // 返回值 m3.ReturnType = new CodeTypeReference(typeof(bool)); // 输入参数 CodeParameterDeclarationExpression pi = new CodeParameterDeclarationExpression(typeof(int), "len"); m3.Parameters.Add(pi); // 输出参数 CodeParameterDeclarationExpression po = new CodeParameterDeclarationExpression(typeof(byte[]), "res"); po.Direction = FieldDirection.Out; //重点 m3.Parameters.Add(po); Console.WriteLine("VB 代码:"); CodeDomProvider provider = CodeDomProvider.CreateProvider("vb"); provider.GenerateCodeFromMember(m3, Console.Out, null); Console.WriteLine("\n\nC# 代码:"); provider = CodeDomProvider.CreateProvider("cs"); provider.GenerateCodeFromMember(m3, Console.Out, null);
要让参数变为输出参数,就要把 Direction 属性设置为 Out。
请看结果。
知道如何定义 out 参数,那ref参数就简单了,比如下面例子。
// 定义类型 CodeTypeDeclaration dt = new CodeTypeDeclaration("MySocket"); // 方法成员 CodeMemberMethod mt = new CodeMemberMethod(); mt.Name = "ReadData"; mt.Attributes = MemberAttributes.Public; // ref 参数 CodeParameterDeclarationExpression pr = new CodeParameterDeclarationExpression(typeof(System.Net.IPEndPoint), "endpoint"); pr.Direction = FieldDirection.Ref; mt.Parameters.Add(pr); dt.Members.Add(mt); CodeDomProvider provider = CodeDomProvider.CreateProvider("cs"); provider.GenerateCodeFromType(dt, Console.Out, null);
生成代码如下。
OK,今天的内容就讲完了,东西不多,也不难。下一篇文章,老周继续厚着脸皮和各位探讨 CodeDom,下一次将介绍一下特性的定义。