MSDN:如何:使用 CodeDOM 创建类
如何:使用 CodeDOM 创建类
下面的过程说明如何创建和编译 CodeDOM 关系图,这个关系图用于生成由以下各项组成的类:两个字段、三个属性、一个方法、一个构造函数和一个入口点。
-
创建将使用 CodeDOM 代码生成类的源代码的控制台应用程序。
在此示例中,生成类被命名为 Sample,生成的代码是名为 SampleCode 的文件中的一个名为 CodeDOMCreatedClass 的类。
-
在生成类中初始化 CodeDOM 关系图,并使用 CodeDOM 方法定义生成的类的成员、构造函数和入口点(Main 方法)。
在此示例中,生成的类包含两个字段、三个属性、一个构造函数、一个方法和一个 Main 方法。
-
在生成类中创建一个语言特定代码提供程序,并调用它的 GenerateCodeFromCompileUnit 方法从关系图生成代码。
-
编译和执行应用程序以生成代码。
在此示例中,生成的代码位于名为 SampleCode 的文件中。 编译并执行此代码,以查看样本输出。
创建将执行 CodeDOM 代码的应用程序
-
创建要包含 CodeDOM 代码的控制台应用程序类。 定义该应用程序类中使用的全局字段,以便引用程序集 (CodeCompileUnit) 和类 (CodeTypeDeclaration);指定生成的源文件的名称,并声明 Main 方法。
using System; using System.Reflection; using System.IO; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; namespace SampleCodeDom { class Sample { CodeCompileUnit targetUnit; CodeTypeDeclaration targetClass; private const string outputFileName = "SampleCode.cs"; static void Main(string[] args) { } } }
初始化 CodeDOM 关系图
-
在控制台应用程序类的构造函数中,初始化程序集和类,并为 CodeDOM 关系图添加适当的声明。
public Sample() { targetUnit = new CodeCompileUnit(); CodeNamespace samples = new CodeNamespace("CodeDOMSample"); samples.Imports.Add(new CodeNamespaceImport("System")); targetClass = new CodeTypeDeclaration("CodeDOMCreatedClass"); targetClass.IsClass = true; targetClass.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed; samples.Types.Add(targetClass); targetUnit.Namespaces.Add(samples); }
向 CodeDOM 关系图添加成员
-
将 CodeMemberField 对象添加到类的 Members 属性,从而向 CodeDOM 关系图添加字段。
public void AddFields() { // Declare the widthValue field. CodeMemberField widthValueField = new CodeMemberField(); widthValueField.Attributes = MemberAttributes.Private; widthValueField.Name = "widthValue"; widthValueField.Type = new CodeTypeReference(typeof(System.Double)); widthValueField.Comments.Add(new CodeCommentStatement( "The width of the object.")); targetClass.Members.Add(widthValueField); // Declare the heightValue field CodeMemberField heightValueField = new CodeMemberField(); heightValueField.Attributes = MemberAttributes.Private; heightValueField.Name = "heightValue"; heightValueField.Type = new CodeTypeReference(typeof(System.Double)); heightValueField.Comments.Add(new CodeCommentStatement( "The height of the object.")); targetClass.Members.Add(heightValueField); }
-
将 CodeMemberProperty 对象添加到类的 Members 属性,从而向 CodeDOM 关系图添加属性。
public void AddProperties() { // Declare the read-only Width property. CodeMemberProperty widthProperty = new CodeMemberProperty(); widthProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; widthProperty.Name = "Width"; widthProperty.HasGet = true; widthProperty.Type = new CodeTypeReference(typeof(System.Double)); widthProperty.Comments.Add(new CodeCommentStatement( "The Width property for the object.")); widthProperty.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"))); targetClass.Members.Add(widthProperty); // Declare the read-only Height property. CodeMemberProperty heightProperty = new CodeMemberProperty(); heightProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; heightProperty.Name = "Height"; heightProperty.HasGet = true; heightProperty.Type = new CodeTypeReference(typeof(System.Double)); heightProperty.Comments.Add(new CodeCommentStatement( "The Height property for the object.")); heightProperty.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue"))); targetClass.Members.Add(heightProperty); // Declare the read only Area property. CodeMemberProperty areaProperty = new CodeMemberProperty(); areaProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; areaProperty.Name = "Area"; areaProperty.HasGet = true; areaProperty.Type = new CodeTypeReference(typeof(System.Double)); areaProperty.Comments.Add(new CodeCommentStatement( "The Area property for the object.")); // Create an expression to calculate the area for the get accessor // of the Area property. CodeBinaryOperatorExpression areaExpression = new CodeBinaryOperatorExpression( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"), CodeBinaryOperatorType.Multiply, new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue")); areaProperty.GetStatements.Add( new CodeMethodReturnStatement(areaExpression)); targetClass.Members.Add(areaProperty); }
-
将 CodeMemberMethod 对象添加到类的 Members 属性,从而向 CodeDOM 关系图添加方法。
public void AddMethod() { // Declaring a ToString method CodeMemberMethod toStringMethod = new CodeMemberMethod(); toStringMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override; toStringMethod.Name = "ToString"; toStringMethod.ReturnType = new CodeTypeReference(typeof(System.String)); CodeFieldReferenceExpression widthReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Width"); CodeFieldReferenceExpression heightReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Height"); CodeFieldReferenceExpression areaReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Area"); // Declaring a return statement for method ToString. CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(); // This statement returns a string representation of the width, // height, and area. string formattedOutput = "The object:" + Environment.NewLine + " width = {0}," + Environment.NewLine + " height = {1}," + Environment.NewLine + " area = {2}"; returnStatement.Expression = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.String"), "Format", new CodePrimitiveExpression(formattedOutput), widthReference, heightReference, areaReference); toStringMethod.Statements.Add(returnStatement); targetClass.Members.Add(toStringMethod); }
-
将 CodeConstructor 对象添加到类的 Members 属性,从而向 CodeDOM 关系图添加构造函数。
public void AddConstructor() { // Declare the constructor CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public | MemberAttributes.Final; // Add parameters. constructor.Parameters.Add(new CodeParameterDeclarationExpression( typeof(System.Double), "width")); constructor.Parameters.Add(new CodeParameterDeclarationExpression( typeof(System.Double), "height")); // Add field initialization logic CodeFieldReferenceExpression widthReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"); constructor.Statements.Add(new CodeAssignStatement(widthReference, new CodeArgumentReferenceExpression("width"))); CodeFieldReferenceExpression heightReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue"); constructor.Statements.Add(new CodeAssignStatement(heightReference, new CodeArgumentReferenceExpression("height"))); targetClass.Members.Add(constructor); }
-
将 CodeEntryPointMethod 对象添加到类的 Members 属性,从而向 CodeDOM 关系图添加入口点。
public void AddEntryPoint() { CodeEntryPointMethod start = new CodeEntryPointMethod(); CodeObjectCreateExpression objectCreate = new CodeObjectCreateExpression( new CodeTypeReference("CodeDOMCreatedClass"), new CodePrimitiveExpression(5.3), new CodePrimitiveExpression(6.9)); // Add the statement: // "CodeDOMCreatedClass testClass = // new CodeDOMCreatedClass(5.3, 6.9);" start.Statements.Add(new CodeVariableDeclarationStatement( new CodeTypeReference("CodeDOMCreatedClass"), "testClass", objectCreate)); // Creat the expression: // "testClass.ToString()" CodeMethodInvokeExpression toStringInvoke = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression("testClass"), "ToString"); // Add a System.Console.WriteLine statement with the previous // expression as a parameter. start.Statements.Add(new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.Console"), "WriteLine", toStringInvoke)); targetClass.Members.Add(start); }
从 CodeDOM 关系图生成代码
-
调用 GenerateCodeFromCompileUnit 方法以便从 CodeDOM 关系图生成源代码。
public void GenerateCSharpCode(string fileName) { CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; using (StreamWriter sourceWriter = new StreamWriter(fileName)) { provider.GenerateCodeFromCompileUnit( targetUnit, sourceWriter, options); } }
创建关系图并生成代码
-
将以上步骤中创建的方法添加到第一步中定义的 Main 方法中。
-
编译和执行生成类。
下面的代码示例显示上述步骤中的代码。
using System; using System.Reflection; using System.IO; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; namespace SampleCodeDom { /// <summary> /// This code example creates a graph using a CodeCompileUnit and /// generates source code for the graph using the CSharpCodeProvider. /// </summary> class Sample { /// <summary> /// Define the compile unit to use for code generation. /// </summary> CodeCompileUnit targetUnit; /// <summary> /// The only class in the compile unit. This class contains 2 fields, /// 3 properties, a constructor, an entry point, and 1 simple method. /// </summary> CodeTypeDeclaration targetClass; /// <summary> /// The name of the file to contain the source code. /// </summary> private const string outputFileName = "SampleCode.cs"; /// <summary> /// Define the class. /// </summary> public Sample() { targetUnit = new CodeCompileUnit(); CodeNamespace samples = new CodeNamespace("CodeDOMSample"); samples.Imports.Add(new CodeNamespaceImport("System")); targetClass = new CodeTypeDeclaration("CodeDOMCreatedClass"); targetClass.IsClass = true; targetClass.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed; samples.Types.Add(targetClass); targetUnit.Namespaces.Add(samples); } /// <summary> /// Adds two fields to the class. /// </summary> public void AddFields() { // Declare the widthValue field. CodeMemberField widthValueField = new CodeMemberField(); widthValueField.Attributes = MemberAttributes.Private; widthValueField.Name = "widthValue"; widthValueField.Type = new CodeTypeReference(typeof(System.Double)); widthValueField.Comments.Add(new CodeCommentStatement( "The width of the object.")); targetClass.Members.Add(widthValueField); // Declare the heightValue field CodeMemberField heightValueField = new CodeMemberField(); heightValueField.Attributes = MemberAttributes.Private; heightValueField.Name = "heightValue"; heightValueField.Type = new CodeTypeReference(typeof(System.Double)); heightValueField.Comments.Add(new CodeCommentStatement( "The height of the object.")); targetClass.Members.Add(heightValueField); } /// <summary> /// Add three properties to the class. /// </summary> public void AddProperties() { // Declare the read-only Width property. CodeMemberProperty widthProperty = new CodeMemberProperty(); widthProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; widthProperty.Name = "Width"; widthProperty.HasGet = true; widthProperty.Type = new CodeTypeReference(typeof(System.Double)); widthProperty.Comments.Add(new CodeCommentStatement( "The Width property for the object.")); widthProperty.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"))); targetClass.Members.Add(widthProperty); // Declare the read-only Height property. CodeMemberProperty heightProperty = new CodeMemberProperty(); heightProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; heightProperty.Name = "Height"; heightProperty.HasGet = true; heightProperty.Type = new CodeTypeReference(typeof(System.Double)); heightProperty.Comments.Add(new CodeCommentStatement( "The Height property for the object.")); heightProperty.GetStatements.Add(new CodeMethodReturnStatement( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue"))); targetClass.Members.Add(heightProperty); // Declare the read only Area property. CodeMemberProperty areaProperty = new CodeMemberProperty(); areaProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; areaProperty.Name = "Area"; areaProperty.HasGet = true; areaProperty.Type = new CodeTypeReference(typeof(System.Double)); areaProperty.Comments.Add(new CodeCommentStatement( "The Area property for the object.")); // Create an expression to calculate the area for the get accessor // of the Area property. CodeBinaryOperatorExpression areaExpression = new CodeBinaryOperatorExpression( new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"), CodeBinaryOperatorType.Multiply, new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue")); areaProperty.GetStatements.Add( new CodeMethodReturnStatement(areaExpression)); targetClass.Members.Add(areaProperty); } /// <summary> /// Adds a method to the class. This method multiplies values stored /// in both fields. /// </summary> public void AddMethod() { // Declaring a ToString method CodeMemberMethod toStringMethod = new CodeMemberMethod(); toStringMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override; toStringMethod.Name = "ToString"; toStringMethod.ReturnType = new CodeTypeReference(typeof(System.String)); CodeFieldReferenceExpression widthReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Width"); CodeFieldReferenceExpression heightReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Height"); CodeFieldReferenceExpression areaReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "Area"); // Declaring a return statement for method ToString. CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(); // This statement returns a string representation of the width, // height, and area. string formattedOutput = "The object:" + Environment.NewLine + " width = {0}," + Environment.NewLine + " height = {1}," + Environment.NewLine + " area = {2}"; returnStatement.Expression = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.String"), "Format", new CodePrimitiveExpression(formattedOutput), widthReference, heightReference, areaReference); toStringMethod.Statements.Add(returnStatement); targetClass.Members.Add(toStringMethod); } /// <summary> /// Add a constructor to the class. /// </summary> public void AddConstructor() { // Declare the constructor CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public | MemberAttributes.Final; // Add parameters. constructor.Parameters.Add(new CodeParameterDeclarationExpression( typeof(System.Double), "width")); constructor.Parameters.Add(new CodeParameterDeclarationExpression( typeof(System.Double), "height")); // Add field initialization logic CodeFieldReferenceExpression widthReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "widthValue"); constructor.Statements.Add(new CodeAssignStatement(widthReference, new CodeArgumentReferenceExpression("width"))); CodeFieldReferenceExpression heightReference = new CodeFieldReferenceExpression( new CodeThisReferenceExpression(), "heightValue"); constructor.Statements.Add(new CodeAssignStatement(heightReference, new CodeArgumentReferenceExpression("height"))); targetClass.Members.Add(constructor); } /// <summary> /// Add an entry point to the class. /// </summary> public void AddEntryPoint() { CodeEntryPointMethod start = new CodeEntryPointMethod(); CodeObjectCreateExpression objectCreate = new CodeObjectCreateExpression( new CodeTypeReference("CodeDOMCreatedClass"), new CodePrimitiveExpression(5.3), new CodePrimitiveExpression(6.9)); // Add the statement: // "CodeDOMCreatedClass testClass = // new CodeDOMCreatedClass(5.3, 6.9);" start.Statements.Add(new CodeVariableDeclarationStatement( new CodeTypeReference("CodeDOMCreatedClass"), "testClass", objectCreate)); // Creat the expression: // "testClass.ToString()" CodeMethodInvokeExpression toStringInvoke = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression("testClass"), "ToString"); // Add a System.Console.WriteLine statement with the previous // expression as a parameter. start.Statements.Add(new CodeMethodInvokeExpression( new CodeTypeReferenceExpression("System.Console"), "WriteLine", toStringInvoke)); targetClass.Members.Add(start); } /// <summary> /// Generate CSharp source code from the compile unit. /// </summary> /// <param name="filename">Output file name</param> public void GenerateCSharpCode(string fileName) { CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; using (StreamWriter sourceWriter = new StreamWriter(fileName)) { provider.GenerateCodeFromCompileUnit( targetUnit, sourceWriter, options); } } /// <summary> /// Create the CodeDOM graph and generate the code. /// </summary> static void Main() { Sample sample = new Sample(); sample.AddFields(); sample.AddProperties(); sample.AddMethod(); sample.AddConstructor(); sample.AddEntryPoint(); sample.GenerateCSharpCode(outputFileName); } } }
编译和执行以上示例后,会生成下面的源代码。
//-------------------------------------------------------------------------- // <auto-generated> // This code was generated by a tool. // Runtime Version:2.0.50727.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //-------------------------------------------------------------------------- namespace CodeDOMSample { using System; public sealed class CodeDOMCreatedClass { // The width of the object. private double widthValue; // The height of the object. private double heightValue; public CodeDOMCreatedClass(double width, double height) { this.widthValue = width; this.heightValue = height; } // The Width property for the object. public double Width { get { return this.widthValue; } } // The Height property for the object. public double Height { get { return this.heightValue; } } // The Area property for the object. public double Area { get { return (this.widthValue * this.heightValue); } } public override string ToString() { return string.Format( "The object:\r\n width = {0},\r\n height = {1},\r\n area = {2}", this.Width, this.Height, this.Area); } public static void Main() { CodeDOMCreatedClass testClass = new CodeDOMCreatedClass(5.3, 6.9); System.Console.WriteLine(testClass.ToString()); } } }
生成的源代码经过编译和执行以后,产生下面的输出。
The object: width = 5.3, height = 6.9, area = 36.57

浙公网安备 33010602011771号