[转载]细说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属性。

然后生成的代码如下图所示。

internal abstract class MyClass {

    public abstract string 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表示方法体中包含注释。

生成的方法如下图所示。

public void SetData((string name, string city, int phone) {
    //方法体
}

默认情况下,参数为输入参数,我们知道,还有两种方法参数——输出参数、引用传参。

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。

请看结果。

VB 代码:
Private Function MakeKey(ByVal len As Integer, ByRef res() As Byte) As Boolean
End Funcation

C# 代码:
private bool MakeKey(int len, out byte[] res) {
}

知道如何定义 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);

生成代码如下。

public class MySocket {
    public virtual void ReadData(ref System.Net.IPEndPoiont endPoint) {
    }
} 

OK,今天的内容就讲完了,东西不多,也不难。下一篇文章,老周继续厚着脸皮和各位探讨 CodeDom,下一次将介绍一下特性的定义。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

3 × 3 =