방법: CodeDOM을 사용하여 클래스 만들기
다음 절차에서는 필드 2개, 속성 3개, 메서드, 생성자 및 진입점을 포함하는 클래스를 생성하는 CodeDOM 그래프를 만들고 컴파일하는 방법을 설명합니다.
CodeDOM 코드를 사용하여 클래스에 대한 소스 코드를 생성하는 콘솔 애플리케이션을 만듭니다.
이 예제에서 생성하는 클래스의 이름은
Sample
이고, 생성된 코드는 SampleCode 파일의CodeDOMCreatedClass
클래스입니다.생성하는 클래스에서 CodeDOM 그래프를 초기화하고 CodeDOM 메서드를 사용하여 생성된 클래스의 멤버, 생성자 및 진입점(
Main
메서드)을 정의합니다.이 예제에서 생성된 클래스에는 필드 2개, 속성 3개, 생성자, 메서드 및
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)
{
}
}
}
Imports System.Reflection
Imports System.IO
Imports System.CodeDom
Imports System.CodeDom.Compiler
Imports Microsoft.CSharp
Class Sample
Private targetUnit As CodeCompileUnit
Private targetClass As CodeTypeDeclaration
Private Const outputFileName As String = "SampleCode.vb"
Shared Sub Main(ByVal args() As String)
End Sub
End Class
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);
}
Public Sub New()
targetUnit = New CodeCompileUnit()
Dim samples As New CodeNamespace("CodeDOMSample")
samples.Imports.Add(New CodeNamespaceImport("System"))
targetClass = New CodeTypeDeclaration("CodeDOMCreatedClass")
targetClass.IsClass = True
targetClass.TypeAttributes = _
TypeAttributes.Public Or TypeAttributes.Sealed
samples.Types.Add(targetClass)
targetUnit.Namespaces.Add(samples)
End Sub
CodeDOM 그래프에 멤버 추가
클래스의 Members 속성에 CodeMemberField 개체를 추가하여 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); }
Public Sub AddFields() ' Declare the widthValue field. Dim widthValueField As New CodeMemberField() widthValueField.Attributes = MemberAttributes.Private widthValueField.Name = "widthValue" widthValueField.Type = _ New CodeTypeReference(GetType(System.Double)) widthValueField.Comments.Add(New CodeCommentStatement( _ "The width of the object.")) targetClass.Members.Add(widthValueField) ' Declare the heightValue field Dim heightValueField As New CodeMemberField() heightValueField.Attributes = MemberAttributes.Private heightValueField.Name = "heightValue" heightValueField.Type = _ New CodeTypeReference(GetType(System.Double)) heightValueField.Comments.Add(New CodeCommentStatement( _ "The height of the object.")) targetClass.Members.Add(heightValueField) End Sub
클래스의 Members 속성에 CodeMemberProperty 개체를 추가하여 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); }
Public Sub AddProperties() ' Declare the read only Width property. Dim widthProperty As New CodeMemberProperty() widthProperty.Attributes = _ MemberAttributes.Public Or MemberAttributes.Final widthProperty.Name = "Width" widthProperty.HasGet = True widthProperty.Type = New CodeTypeReference(GetType(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. Dim heightProperty As New CodeMemberProperty() heightProperty.Attributes = _ MemberAttributes.Public Or MemberAttributes.Final heightProperty.Name = "Height" heightProperty.HasGet = True heightProperty.Type = New CodeTypeReference(GetType(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. Dim areaProperty As New CodeMemberProperty() areaProperty.Attributes = _ MemberAttributes.Public Or MemberAttributes.Final areaProperty.Name = "Area" areaProperty.HasGet = True areaProperty.Type = New CodeTypeReference(GetType(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. Dim areaExpression As New CodeBinaryOperatorExpression( _ New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "widthValue"), _ CodeBinaryOperatorType.Multiply, _ New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "heightValue")) areaProperty.GetStatements.Add( _ New CodeMethodReturnStatement(areaExpression)) targetClass.Members.Add(areaProperty) End Sub
클래스의 Members 속성에 CodeMemberMethod 개체를 추가하여 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); }
Public Sub AddMethod() ' Declaring a ToString method. Dim toStringMethod As New CodeMemberMethod() toStringMethod.Attributes = _ MemberAttributes.Public Or MemberAttributes.Override toStringMethod.Name = "ToString" toStringMethod.ReturnType = _ New CodeTypeReference(GetType(System.String)) Dim widthReference As New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "Width") Dim heightReference As New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "Height") Dim areaReference As New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "Area") ' Declaring a return statement for method ToString. Dim returnStatement As New CodeMethodReturnStatement() ' This statement returns a string representation of the width, ' height, and area. Dim formattedOutput As String = "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) End Sub
클래스의 Members 속성에 CodeConstructor 개체를 추가하여 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); }
Public Sub AddConstructor() ' Declare the constructor Dim constructor As New CodeConstructor() constructor.Attributes = _ MemberAttributes.Public Or MemberAttributes.Final ' Add parameters. constructor.Parameters.Add( _ New CodeParameterDeclarationExpression( _ GetType(System.Double), "width")) constructor.Parameters.Add( _ New CodeParameterDeclarationExpression( _ GetType(System.Double), "height")) ' Add field initialization logic Dim widthReference As New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "widthValue") constructor.Statements.Add(New CodeAssignStatement( _ widthReference, New CodeArgumentReferenceExpression("width"))) Dim heightReference As New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), "heightValue") constructor.Statements.Add( _ New CodeAssignStatement(heightReference, _ New CodeArgumentReferenceExpression("height"))) targetClass.Members.Add(constructor) End Sub
클래스의 Members 속성에 CodeEntryPointMethod 개체를 추가하여 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); }
Public Sub AddEntryPoint() Dim start As New CodeEntryPointMethod() Dim objectCreate As 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()" Dim toStringInvoke As 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) End Sub
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);
}
}
Public Sub GenerateVBCode(ByVal fileName As String)
Dim provider As CodeDomProvider
provider = CodeDomProvider.CreateProvider("VisualBasic")
Dim options As New CodeGeneratorOptions()
Dim sourceWriter As New StreamWriter(fileName)
Try
provider.GenerateCodeFromCompileUnit( _
targetUnit, sourceWriter, options)
Finally
sourceWriter.Dispose()
End Try
End Sub
그래프 만들기 및 코드 생성
앞의 단계에서 만든 메서드를 첫 번째 단계에서 정의한
Main
메서드에 추가합니다.static void Main() { Sample sample = new Sample(); sample.AddFields(); sample.AddProperties(); sample.AddMethod(); sample.AddConstructor(); sample.AddEntryPoint(); sample.GenerateCSharpCode(outputFileName); }
Shared Sub Main() Dim sample As New Sample() sample.AddFields() sample.AddProperties() sample.AddMethod() sample.AddConstructor() sample.AddEntryPoint() sample.GenerateVBCode(outputFileName) End Sub End Class
생성하는 클래스를 컴파일 및 실행합니다.
예시
다음 코드 예제에서는 앞의 단계에서 생성한 코드를 보여 줍니다.
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);
}
}
}
Imports System.Reflection
Imports System.IO
Imports System.CodeDom
Imports System.CodeDom.Compiler
' This code example creates a graph using a CodeCompileUnit and
' generates source code for the graph using the VBCodeProvider.
Class Sample
' Define the compile unit to use for code generation.
Private targetUnit As CodeCompileUnit
' The only class in the compile unit. This class contains 2 fields,
' 3 properties, a constructor, an entry point, and 1 simple method.
Private targetClass As CodeTypeDeclaration
' The name of the file to contain the source code.
Private Const outputFileName As String = "SampleCode.vb"
' Define the class.
Public Sub New()
targetUnit = New CodeCompileUnit()
Dim samples As New CodeNamespace("CodeDOMSample")
samples.Imports.Add(New CodeNamespaceImport("System"))
targetClass = New CodeTypeDeclaration("CodeDOMCreatedClass")
targetClass.IsClass = True
targetClass.TypeAttributes = _
TypeAttributes.Public Or TypeAttributes.Sealed
samples.Types.Add(targetClass)
targetUnit.Namespaces.Add(samples)
End Sub
' Adds two fields to the class.
Public Sub AddFields()
' Declare the widthValue field.
Dim widthValueField As New CodeMemberField()
widthValueField.Attributes = MemberAttributes.Private
widthValueField.Name = "widthValue"
widthValueField.Type = _
New CodeTypeReference(GetType(System.Double))
widthValueField.Comments.Add(New CodeCommentStatement( _
"The width of the object."))
targetClass.Members.Add(widthValueField)
' Declare the heightValue field
Dim heightValueField As New CodeMemberField()
heightValueField.Attributes = MemberAttributes.Private
heightValueField.Name = "heightValue"
heightValueField.Type = _
New CodeTypeReference(GetType(System.Double))
heightValueField.Comments.Add(New CodeCommentStatement( _
"The height of the object."))
targetClass.Members.Add(heightValueField)
End Sub
' Add three properties to the class.
Public Sub AddProperties()
' Declare the read only Width property.
Dim widthProperty As New CodeMemberProperty()
widthProperty.Attributes = _
MemberAttributes.Public Or MemberAttributes.Final
widthProperty.Name = "Width"
widthProperty.HasGet = True
widthProperty.Type = New CodeTypeReference(GetType(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.
Dim heightProperty As New CodeMemberProperty()
heightProperty.Attributes = _
MemberAttributes.Public Or MemberAttributes.Final
heightProperty.Name = "Height"
heightProperty.HasGet = True
heightProperty.Type = New CodeTypeReference(GetType(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.
Dim areaProperty As New CodeMemberProperty()
areaProperty.Attributes = _
MemberAttributes.Public Or MemberAttributes.Final
areaProperty.Name = "Area"
areaProperty.HasGet = True
areaProperty.Type = New CodeTypeReference(GetType(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.
Dim areaExpression As New CodeBinaryOperatorExpression( _
New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "widthValue"), _
CodeBinaryOperatorType.Multiply, _
New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "heightValue"))
areaProperty.GetStatements.Add( _
New CodeMethodReturnStatement(areaExpression))
targetClass.Members.Add(areaProperty)
End Sub
' Adds a method to the class. This method multiplies values stored
' in both fields.
Public Sub AddMethod()
' Declaring a ToString method.
Dim toStringMethod As New CodeMemberMethod()
toStringMethod.Attributes = _
MemberAttributes.Public Or MemberAttributes.Override
toStringMethod.Name = "ToString"
toStringMethod.ReturnType = _
New CodeTypeReference(GetType(System.String))
Dim widthReference As New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "Width")
Dim heightReference As New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "Height")
Dim areaReference As New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "Area")
' Declaring a return statement for method ToString.
Dim returnStatement As New CodeMethodReturnStatement()
' This statement returns a string representation of the width,
' height, and area.
Dim formattedOutput As String = "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)
End Sub
' Add a constructor to the class.
Public Sub AddConstructor()
' Declare the constructor
Dim constructor As New CodeConstructor()
constructor.Attributes = _
MemberAttributes.Public Or MemberAttributes.Final
' Add parameters.
constructor.Parameters.Add( _
New CodeParameterDeclarationExpression( _
GetType(System.Double), "width"))
constructor.Parameters.Add( _
New CodeParameterDeclarationExpression( _
GetType(System.Double), "height"))
' Add field initialization logic
Dim widthReference As New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "widthValue")
constructor.Statements.Add(New CodeAssignStatement( _
widthReference, New CodeArgumentReferenceExpression("width")))
Dim heightReference As New CodeFieldReferenceExpression( _
New CodeThisReferenceExpression(), "heightValue")
constructor.Statements.Add( _
New CodeAssignStatement(heightReference, _
New CodeArgumentReferenceExpression("height")))
targetClass.Members.Add(constructor)
End Sub
' Add an entry point to the class.
Public Sub AddEntryPoint()
Dim start As New CodeEntryPointMethod()
Dim objectCreate As 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()"
Dim toStringInvoke As 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)
End Sub
' Generate Visual Basic source code from the compile unit.
Public Sub GenerateVBCode(ByVal fileName As String)
Dim provider As CodeDomProvider
provider = CodeDomProvider.CreateProvider("VisualBasic")
Dim options As New CodeGeneratorOptions()
Dim sourceWriter As New StreamWriter(fileName)
Try
provider.GenerateCodeFromCompileUnit( _
targetUnit, sourceWriter, options)
Finally
sourceWriter.Dispose()
End Try
End Sub
' Create the CodeDOM graph and generate the code.
Shared Sub Main()
Dim sample As New Sample()
sample.AddFields()
sample.AddProperties()
sample.AddMethod()
sample.AddConstructor()
sample.AddEntryPoint()
sample.GenerateVBCode(outputFileName)
End Sub
End Class
앞의 예제를 컴파일 및 실행하면 다음 소스 코드가 생성됩니다.
//--------------------------------------------------------------------------
// <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());
}
}
}
'--------------------------------------------------------------------------
' <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>
'--------------------------------------------------------------------------
Option Strict Off
Option Explicit On
Namespace CodeDOMSample
Public NotInheritable Class CodeDOMCreatedClass
'The width of the object.
Private widthValue As Double
'The height of the object.
Private heightValue As Double
Public Sub New(ByVal width As Double, ByVal height As Double)
MyBase.New
Me.widthValue = width
Me.heightValue = height
End Sub
'The width property for the object.
Public ReadOnly Property Width() As Double
Get
Return Me.widthValue
End Get
End Property
'The Height property for the object.
Public ReadOnly Property Height() As Double
Get
Return Me.heightValue
End Get
End Property
'The Area property for the object.
Public ReadOnly Property Area() As Double
Get
Return (Me.widthValue * Me.heightValue)
End Get
End Property
Public Overrides Function ToString() As String
Return String.Format("The object:"& _
Global.Microsoft.VisualBasic.ChrW(13)& _
Global.Microsoft.VisualBasic.ChrW(10)& _
" width = {0},"&Global.Microsoft.VisualBasic.ChrW(13)& _
Global.Microsoft.VisualBasic.ChrW(10)& _
" height = {1},"&Global.Microsoft.VisualBasic.ChrW(13)& _
Global.Microsoft.VisualBasic.ChrW(10)&" area = {2}", _
Me.Width, Me.Height, Me.Area)
End Function
Public Shared Sub Main()
Dim testClass As CodeDOMCreatedClass = _
New CodeDOMCreatedClass(5.3, 6.9)
System.Console.WriteLine(testClass.ToString)
End Sub
End Class
End Namespace
생성된 소스 코드를 컴파일 및 실행하면 다음 출력이 생성됩니다.
The object:
width = 5.3,
height = 6.9,
area = 36.57
코드 컴파일
- 이 코드 예제를 성공적으로 실행하려면
FullTrust
권한이 설정되어 있어야 합니다.
참고 항목
.NET
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기