实例浅学.NET代码对象模型CodeDOM
.NET Framework 中包含一个名为“代码文档对象模型”(CodeDOM) 的机制,该机制使编写源代码的程序的开发人员可以在运行时,根据表示所呈现代码的单一模型,用多种编程语言生成源代码。
为表示源代码,CodeDOM 元素相互链接以形成一个数据结构(称为 CodeDOM 图),它以某种源代码的结构为模型。
以下一段代码是在网络上找的一个可以生成代码程序的一部分关键代码,作用就是通过代码文档对象模型的操作来生成程序代码。其中有用到另外一个dll文件的某些方法DataAccess类的,是关于对数据库访问操作的。selectName是用户选择的表名。
private void GetGeneralCode(string selectName,string name)
{
//要用具体某种语言生成源代码,需要一个 CodeDOM 图来表示要生成的源代码的结构,以及一个代码生成器。
//要获取代码生成器,首先要创建目标语言的 CodeDomProvider。然后调用 CodeDomProvider.CreateGenerator 方法以创建代码生成器。
//提供对 C# 代码生成器和代码编译器的实例的访问
CSharpCodeProvider provider = new CSharpCodeProvider();
//ICodeGenerator定义用于生成代码的接口
//provide.CreateGenerator();获取 C# 代码生成器的实例。
//设置生成的代码为C#语言格式的
ICodeGenerator generator = provider.CreateGenerator();
//使用默认编码和缓冲区大小,为指定路径上的指定文件初始化 StreamWriter 类的新实例
//创建一个可以写入的 TextWriter,因为为包含 CodeDOM 图的 CodeCompileUnit 生成代码,需要调用代码生成器的 ICodeGenerator.GenerateCodeFromCompileUnit 方法。该方法有一个可用来生成源代码的 TextWriter 参数
StreamWriter writer = new StreamWriter(@"c:\" + txtClassName.Text + ".cs",false);
//为 CodeDOM 程序图形提供容器
//代码生成图通常包含在 CodeCompileUnit 中
CodeCompileUnit unit = new CodeCompileUnit();
//表示命名空间声明
//结果:namespace SQLNetPlus{}
CodeNamespace nspace = new CodeNamespace("SQLNetPlus"); //添加名称空间
//Imports命名空间使用的命名空间导入指令集合
//CodeNamespaceImport("")使用要导入的指定命名空间初始化
//表示命名空间SQLNetPlus引用
//结果:using System;
nspace.Imports.Add(new CodeNamespaceImport("System"));
//CodeTypeDeclaration可用来表示声明类、结构、接口或枚举的代码
//声明一个类或者结构或者接口或者枚举类型
//结果:class test {}
CodeTypeDeclaration info = new CodeTypeDeclaration(txtClassName.Text);
//表示一个类型的实例构造函数的声明
//初始化一个构造函数
//结果:test() {}
CodeConstructor ct = new CodeConstructor();
DataAccess da = getDataAccess();
DataSet ds = da.GetDataSet(selectName,false);
if(name != "proc")
{
//结果:public test(){}
ct.Attributes=MemberAttributes.Public;
//CodeSnippetStatement使用原义代码片断表示一条语句
//结果:
// public test() {
// this.conStr=System.Configuration.ConfigurationSettings.AppSettings["DBConnStr"];
// if( this.conStr==null || this.conStr.Length==0)
// throw new Exception();
// }
ct.Statements.Add(new CodeSnippetStatement("this.conStr=System.Configuration.ConfigurationSettings.AppSettings[\"DBConnStr\"];")); //内容
ct.Statements.Add(new CodeSnippetStatement("if( this.conStr==null || this.conStr.Length==0)")); //内容
ct.Statements.Add(new CodeSnippetStatement("throw new Exception();"));
//为类info添加成员
info.Members.Add(ct);
for(int i=0;i<ds.Tables[0].Rows.Count;i++)
{
//私有成员变量,直接以字段名(包括s_)作变量名
//CodeMemberField表示某种类型的字段的声明
//结果:private int s_id;
CodeMemberField f = new CodeMemberField();
f.Name="s_" + ds.Tables[0].Rows[i]["Name"];
f.Type = new CodeTypeReference((da.getTypeString(ds.Tables[0].Rows[i]["datatype"].ToString())));
info.Members.Add(f);
//公共属性,以字段名作属性名
//CodeMemberProperty表示某种类型的属性的声明
//结果:
// public int id {
// get {
// return this.s_id;
// }
// set {
// this.s_id = value;
// }
// }
CodeMemberProperty p = new CodeMemberProperty();
//结果:id{}
p.Name=ds.Tables[0].Rows[i]["Name"].ToString();
//结果:int id{}
p.Type=f.Type;
//结果:public int id{}
p.Attributes = MemberAttributes.Public|MemberAttributes.Final;
//CodeThisReferenceExpression表示对当前本地类实例的引用,它可以表示“this”或“me”所引用的类对象
//CodeFieldReferenceExpression表示对某字段的引用
//public CodeFieldReferenceExpression(CodeExpression targetObject, string fieldName);TargetObject 属性指定包含字段的对象(this)。FieldName 属性指定要引用的字段的名称。
//CodeMethodReturnStatement可用于表示返回值语句
//CodePropertySetValueReferenceExpression表示属性集方法内的属性集方法调用的值参数
//CodeAssignStatement简单的赋值语句
// public int id {
// get {
// return this.s_id;
// }
// set {
// this.s_id = value;
// }
// }
p.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),f.Name)));
p.SetStatements.Add(new CodeAssignStatement(
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),f.Name),
new CodePropertySetValueReferenceExpression()));
info.Members.Add(p);
}
}
else
{
//结果:public test(){}
ct.Attributes=MemberAttributes.Public;
info.Members.Add(ct);
//添加方法
//CodeMemberMethod表示某种类型的方法的声明
//声明一个方法
CodeMemberMethod m = new CodeMemberMethod();
//设置方法的返回类型
//CodeTypeReference("");表示对某类型的引用
//结果:public System.Data.DataSet ExecProc_SearchByPage()
m.ReturnType = new CodeTypeReference("System.Data.DataSet");
m.Name = "ExecProc_" + selectName;
m.Attributes = MemberAttributes.Public|MemberAttributes.Final;
int rows = ds.Tables[0].Rows.Count;
//CodeSnippetStatement使用原义代码片断表示一条语句,直接的C#语句
//结果:SqlParameter[] parms =new SqlParameter[11];
CodeSnippetStatement codebody = null;
codebody = new CodeSnippetStatement("SqlParameter[] parms =new SqlParameter[" + (rows+1).ToString() + "];");
m.Statements.Add(codebody);
for(int i=0;i<rows;i++)
{
string paramName = ds.Tables[0].Rows[i]["name"].ToString();
string paramName1 = "p_" + paramName.Substring(1,paramName.Length-1);
//CodeTypeReference表示对某类型的引用
//保存数据类型
CodeTypeReference paramType = new CodeTypeReference((da.getTypeString(ds.Tables[0].Rows[i]["datatype"].ToString())));
//CodeParameterDeclarationExpression表示方法、属性或构造函数的参数声明
//public CodeParameterDeclarationExpression(CodeTypeReference type,string name);
//type CodeTypeReference,指示要声明的参数的类型。 name 要声明的参数的名称。
//结果:string p_tblName
CodeParameterDeclarationExpression parameters = null;
parameters = new CodeParameterDeclarationExpression(paramType, paramName1);
//为方法添加参数
//public System.Data.DataSet ExecProc_SearchByPage(strint p_tblName)
m.Parameters.Add(parameters);
//获得该参数是否是输出参数
string paramOutput = ds.Tables[0].Rows[i]["isoutparam"].ToString();
//直接生成.NET语句
//结果:parms[0]=new SqlParameter("@tblName", p_tblName);
codebody = new CodeSnippetStatement("parms[" + i.ToString() + "]=new SqlParameter(\"" + paramName + "\", " + paramName1 + ");");
m.Statements.Add(codebody);
//如果是输出参数
if(paramOutput == "1")
{
//一条.NET语句
//parms[4].Direction=ParameterDirection.Output;
codebody = new CodeSnippetStatement("parms[" + i.ToString() + "].Direction=ParameterDirection.Output;");
m.Statements.Add(codebody);
}
}
//一条.NET语句
//结果:parms[10]=new SqlParameter("RETURN_VALUE", SqlDbType.Int);
//存储过程执行,返回结果为int型,如为0说明执行成功,如果为非0说明执行失败
codebody = new CodeSnippetStatement("parms[" + rows.ToString() + "]=new SqlParameter(\"RETURN_VALUE\", SqlDbType.Int);");
m.Statements.Add(codebody);
//一条.NET语句
//结果:parms[10].Direction=ParameterDirection.ReturnValue;
codebody = new CodeSnippetStatement("parms[" + rows.ToString() + "].Direction=ParameterDirection.ReturnValue;");
m.Statements.Add(codebody);
//一条.NET语句
//结果:return ExecuteDataset("SearchByPage",parms);
codebody = new CodeSnippetStatement("return ExecuteDataset(\"" + selectName + "\",parms);");
m.Statements.Add(codebody);
//将方法m添加到类info中
info.Members.Add(m);
}
//将类info添加到命名空间nspace中
nspace.Types.Add(info);
//代码文档对象模型CodeDOM添加命名空间
unit.Namespaces.Add(nspace);
//为指定的代码文档对象模型 (CodeDOM) 编译单元生成代码,并使用指定的选项将代码输出到指定的文本编写器。
//unit要生成的代码,writer输出的代码的目标,CodeGeneratorOptions表示代码生成器使用的一组选项
//生成代码unit保存到writer中
generator.GenerateCodeFromCompileUnit(unit,writer,new CodeGeneratorOptions());
//关闭输出流
writer.Close();
StreamReader sr = new StreamReader(@"c:\" + txtClassName.Text + ".cs",System.Text.Encoding.GetEncoding("GB2312"));
txtCode.Text = sr.ReadToEnd();
sr.Close();
}
//总结:
/*
* 1、一个代码生成器实例CSharpCodeProvider provider = new CSharpCodeProvider();
* 2、定义代码生成接口,设置代码生成编译器 ICodeGenerator generator = provider.CreateGenerator();
* 3、定义CodeDOM 程序图形提供容器 CodeCompileUnit unit = new CodeCompileUnit();
*
* 4、声明命名空间 CodeNamespace nspace = new CodeNamespace("SQLNetPlus");
* 5、设置命名空间引用 nspace.Imports.Add(new CodeNamespaceImport("System"));
*
* 6、声明一个类 CodeTypeDeclaration info = new CodeTypeDeclaration(txtClassName.Text);
* 7、声明一个未知构造函数 CodeConstructor ct = new CodeConstructor();
* 8、设置构造函数的可访问性 ct.Attributes=MemberAttributes.Public;
* 9、把构造函数赋值给类,类就有了构造函数 info.Members.Add(ct);
* 10、为类添加代码语句 ct.Statements.Add(new CodeSnippetStatement("throw new Exception();"));
*
* 11、定义字段成员 CodeMemberField f = new CodeMemberField();
* 12、定义字段类型和字段名 f.Name=""; f.Type = new CodeTypeReference("类型名");
* 13、为类添加字段成员 info.Members.Add(f);
*
* 14、定义属性成员 CodeMemberProperty p = new CodeMemberProperty();
* 15、定义属性类型和属性名 p.Name="" p.Type=new CodeTypeReference("类型名");
* 16、定义属性的可访问性 p.Attributes = MemberAttributes.Public|MemberAttributes.Final;
* 17、定义属性的读写
* p.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),f.Name)));
p.SetStatements.Add(new CodeAssignStatement(
new CodeFieldReferenceExpression(new CodeThisReferenceExpression(),f.Name),
new CodePropertySetValueReferenceExpression()));
* 18、为类添加属性成员 info.Members.Add(p);
*
* 19、声明一个方法属性 CodeMemberMethod m = new CodeMemberMethod();
* 20、定义方法属性返回值类型 m.ReturnType = new CodeTypeReference("System.Data.DataSet");
* 21、设置方法属性名称和可访问性 m.Name = "";
* 22、设置方法属性的可访问性 m.Attributes = MemberAttributes.Public|MemberAttributes.Final;
* 23、定义一个参数 CodeParameterDeclarationExpression parameters = new CodeParameterDeclarationExpression(参数类型,"参数名");
* 24、将参数赋给方法 m.Parameters.Add(parameters);
* 25、将方法添加到类中,使之成为该类的方法对象 info.Members.Add(m);
*
* 26、把类添加到命名空间中 nspace.Types.Add(info);
* 27、创建一个可输出的流,用以输出保存生成的代码 StreamWriter writer = new StreamWriter(@"c:\" + txtClassName.Text + ".cs",false);
* 28、把命名空间添加到CodeDOM程序图形容器中 unit.Namespaces.Add(nspace);
* 29、将图形容器中的代码输出到流中 generator.GenerateCodeFromCompileUnit(unit,writer,new CodeGeneratorOptions());
* 30、关闭输出流 writer.Close();
*/
浙公网安备 33010602011771号