CodeDOM fraph에서 소스 코드 생성 및 컴파일

System.CodeDom.Compiler 네임스페이스는 CodeDOM 개체 그래프에서 소스 코드를 생성하고 지원되는 컴파일러를 통한 컴파일을 관리하기 위한 인터페이스를 제공합니다. 코드 공급자는 CodeDOM 그래프에 따라 특정 프로그래밍 언어로 소스 코드를 생성할 수 있습니다. CodeDomProvider에서 파생되는 클래스는 일반적으로 공급자가 지원하는 언어의 코드를 생성 및 컴파일하기 위한 메서드를 제공할 수 있습니다.

CodeDOM 코드 공급자를 사용하여 소스 코드 생성

특정 언어로 소스 코드를 생성하려면 생성할 소스 코드의 구조를 나타내는 CodeDOM 그래프가 필요합니다.

다음 예제에서는 CSharpCodeProvider 인스턴스를 만드는 방법을 보여 줍니다.

CSharpCodeProvider^ provider = gcnew CSharpCodeProvider();
CSharpCodeProvider provider = new CSharpCodeProvider();
Dim provider As New CSharpCodeProvider()

코드 생성 그래프는 일반적으로 CodeCompileUnit에 포함되어 있습니다. CodeDOM 그래프를 CodeCompileUnit 포함하는 코드를 생성하려면 코드 공급자의 메서드를 GenerateCodeFromCompileUnit 호출합니다. 이 메서드에는 소스 코드를 생성하는 데 사용하는 매개 변수가 있으므로 먼저 쓸 수 있는 매개 변수 TextWriterTextWriter 만들어야 하는 경우도 있습니다. 다음 예제에서는 a에서 CodeCompileUnit 코드를 생성하고 생성된 소스 코드를 HelloWorld.cs 파일에 쓰는 방법을 보여 줍니다.

public:
    static String^ GenerateCSharpCode(CodeCompileUnit^ compileunit)
    {
        // Generate the code with the C# code provider.
        CSharpCodeProvider^ provider = gcnew CSharpCodeProvider();

        // Build the output file name.
        String^ sourceFile;
        if (provider->FileExtension[0] == '.')
        {
           sourceFile = "HelloWorld" + provider->FileExtension;
        }
        else
        {
           sourceFile = "HelloWorld." + provider->FileExtension;
        }

        // Create a TextWriter to a StreamWriter to the output file.
        StreamWriter^ sw = gcnew StreamWriter(sourceFile, false);
        IndentedTextWriter^ tw = gcnew IndentedTextWriter(sw, "    ");

            // Generate source code using namespace the code provider.
        provider->GenerateCodeFromCompileUnit(compileunit, tw,
            gcnew CodeGeneratorOptions());

        // Close the output file.
        tw->Close();
        sw->Close();

        return sourceFile;
    }
public static string GenerateCSharpCode(CodeCompileUnit compileunit)
{
    // Generate the code with the C# code provider.
    CSharpCodeProvider provider = new CSharpCodeProvider();

    // Build the output file name.
    string sourceFile;
    if (provider.FileExtension[0] == '.')
    {
       sourceFile = "HelloWorld" + provider.FileExtension;
    }
    else
    {
       sourceFile = "HelloWorld." + provider.FileExtension;
    }

    // Create a TextWriter to a StreamWriter to the output file.
    using (StreamWriter sw = new StreamWriter(sourceFile, false))
    {
        IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");

        // Generate source code using the code provider.
        provider.GenerateCodeFromCompileUnit(compileunit, tw,
            new CodeGeneratorOptions());

        // Close the output file.
        tw.Close();
    }

    return sourceFile;
}
Public Shared Function GenerateCSharpCode(compileunit As CodeCompileUnit) As String
    ' Generate the code with the C# code provider.
    Dim provider As New CSharpCodeProvider()

    ' Build the output file name.
    Dim sourceFile As String
    If provider.FileExtension(0) = "." Then
        sourceFile = "HelloWorld" + provider.FileExtension
    Else
        sourceFile = "HelloWorld." + provider.FileExtension
    End If

    ' Create a TextWriter to a StreamWriter to the output file.
    Using sw As New StreamWriter(sourceFile, false)
        Dim tw As New IndentedTextWriter(sw, "    ")

        ' Generate source code Imports the code provider.
        provider.GenerateCodeFromCompileUnit(compileunit, tw, _
            New CodeGeneratorOptions())

        ' Close the output file.
        tw.Close()
    End Using

    Return sourceFile
End Function

CodeDOM 코드 공급자를 사용하여 어셈블리 컴파일

컴파일 호출

CodeDom 공급자를 사용하여 어셈블리를 컴파일하려면 컴파일러가 있는 언어로 컴파일할 소스 코드나 컴파일할 소스 코드를 생성할 수 있는 CodeDOM 그래프가 있어야 합니다.

CodeDOM 그래프에서 컴파일하는 경우 그래프를 포함하는 CodeCompileUnit을 코드 공급자의 CompileAssemblyFromDom 메서드에 전달합니다. 컴파일러가 이해할 수 있는 언어의 소스 코드 파일이 있는 경우 소스 코드를 포함하는 파일의 이름을 CodeDom 공급자의 CompileAssemblyFromFile 메서드에 전달합니다. 컴파일러가 이해할 수 있는 언어의 소스 코드를 포함하는 문자열을 CodeDom 공급자의 CompileAssemblyFromSource 메서드에 전달할 수도 있습니다.

컴파일 매개 변수 구성

CodeDom 공급자의 모든 표준 컴파일 호출 메서드에는 컴파일에 사용할 옵션을 나타내는 CompilerParameters 형식의 매개 변수가 있습니다.

의 속성CompilerParameters에서 출력 어셈블리의 OutputAssembly 파일 이름을 지정할 수 있습니다. 지정하지 않으면 기본 출력 파일 이름이 사용됩니다.

기본적으로 새 CompilerParameters 새 속성이 .로 설정된 상태로 GenerateExecutable 초기화됩니다 false. 실행 프로그램을 컴파일하는 경우 속성을 true.로 설정 GenerateExecutable 해야 합니다. 이 형식으로 GenerateExecutablefalse설정되면 컴파일러는 클래스 라이브러리를 생성합니다.

CodeDOM 그래프에서 실행 파일을 컴파일하는 경우 CodeEntryPointMethod가 그래프에 정의되어 있어야 합니다. 여러 코드 진입점이 있는 경우 사용할 진입점을 정의하는 클래스의 이름으로 속성을 CompilerParameters 설정 MainClass 해야 할 수 있습니다.

생성된 실행 파일에 디버그 정보를 포함하려면 속성을 true.로 설정합니다IncludeDebugInformation.

프로젝트에서 어셈블리를 참조하는 경우 컴파일을 호출할 때 사용하는 속성 CompilerParameters 으로 어셈블리 이름을 항목 StringCollection 으로 ReferencedAssemblies 지정해야 합니다.

속성을 .로 설정하여 디스크가 아닌 메모리에 기록되는 어셈블리를 GenerateInMemory 컴파일할 true수 있습니다. 어셈블리가 메모리에 생성되면 코드에서 CompilerResultsCompiledAssembly 속성을 통해 생성된 어셈블리에 대한 참조를 가져올 수 있습니다. 어셈블리가 디스크에 기록되는 경우 생성된 어셈블리의 경로를 해당 속성CompilerResults에서 PathToAssembly 가져올 수 있습니다.

컴파일 프로세스를 호출할 때 사용할 사용자 지정 명령줄 인수 문자열을 지정하려면 CompilerOptions 속성에 문자열을 설정합니다.

컴파일러 프로세스를 호출하는 데 Win32 보안 토큰이 필요한 경우 UserToken 속성에 토큰을 지정합니다.

Win32 리소스 파일을 컴파일된 어셈블리에 연결하려면 Win32Resource 속성에서 Win32 리소스 파일의 이름을 지정합니다.

컴파일을 중단할 경고 수준을 지정하려면 컴파일을 중단할 경고 수준을 나타내는 정수로 WarningLevel 속성을 설정합니다. 속성을 true.로 설정 TreatWarningsAsErrors 하여 경고가 발생하는 경우 컴파일러가 컴파일을 중지하도록 구성할 수도 있습니다.

다음 코드 예제에서는 CodeDomProvider 클래스에서 파생된 CodeDom 공급자를 사용하여 소스 파일을 컴파일하는 방법을 보여 줍니다.

public:
    static bool CompileCSharpCode(String^ sourceFile, String^ exeFile)
    {
        CSharpCodeProvider^ provider = gcnew CSharpCodeProvider();

        // Build the parameters for source compilation.
        CompilerParameters^ cp = gcnew CompilerParameters();

        // Add an assembly reference.
        cp->ReferencedAssemblies->Add( "System.dll" );

        // Generate an executable instead of
        // a class library.
        cp->GenerateExecutable = true;

        // Set the assembly file name to generate.
        cp->OutputAssembly = exeFile;

        // Save the assembly as a physical file.
        cp->GenerateInMemory = false;

        // Invoke compilation.
        CompilerResults^ cr = provider->CompileAssemblyFromFile(cp, sourceFile);

       if (cr->Errors->Count > 0)
       {
           // Display compilation errors.
            Console::WriteLine("Errors building {0} into {1}",
                sourceFile, cr->PathToAssembly);
            for each (CompilerError^ ce in cr->Errors)
            {
                Console::WriteLine("  {0}", ce->ToString());
                Console::WriteLine();
            }
        }
        else
        {
            Console::WriteLine("Source {0} built into {1} successfully.",
                sourceFile, cr->PathToAssembly);
        }

        // Return the results of compilation.
        if (cr->Errors->Count > 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
public static bool CompileCSharpCode(string sourceFile, string exeFile)
{
    CSharpCodeProvider provider = new CSharpCodeProvider();

    // Build the parameters for source compilation.
    CompilerParameters cp = new CompilerParameters();

    // Add an assembly reference.
    cp.ReferencedAssemblies.Add( "System.dll" );

    // Generate an executable instead of
    // a class library.
    cp.GenerateExecutable = true;

    // Set the assembly file name to generate.
    cp.OutputAssembly = exeFile;

    // Save the assembly as a physical file.
    cp.GenerateInMemory = false;

    // Invoke compilation.
    CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);

   if (cr.Errors.Count > 0)
   {
       // Display compilation errors.
        Console.WriteLine("Errors building {0} into {1}",
            sourceFile, cr.PathToAssembly);
        foreach (CompilerError ce in cr.Errors)
        {
            Console.WriteLine("  {0}", ce.ToString());
            Console.WriteLine();
        }
    }
    else
    {
        Console.WriteLine("Source {0} built into {1} successfully.",
            sourceFile, cr.PathToAssembly);
    }

    // Return the results of compilation.
    if (cr.Errors.Count > 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}
Public Shared Function CompileCSharpCode(sourceFile As String, _
    exeFile As String) As Boolean
    Dim provider As New CSharpCodeProvider()

    ' Build the parameters for source compilation.
    Dim cp As New CompilerParameters()

    ' Add an assembly reference.
    cp.ReferencedAssemblies.Add("System.dll")

    ' Generate an executable instead of
    ' a class library.
    cp.GenerateExecutable = true

    ' Set the assembly file name to generate.
    cp.OutputAssembly = exeFile

    ' Save the assembly as a physical file.
    cp.GenerateInMemory = false

    ' Invoke compilation.
    Dim cr As CompilerResults = provider.CompileAssemblyFromFile(cp, sourceFile)

    If cr.Errors.Count > 0 Then
        ' Display compilation errors.
        Console.WriteLine("Errors building {0} into {1}", _
            sourceFile, cr.PathToAssembly)
        For Each ce As CompilerError In cr.Errors
            Console.WriteLine("  {0}", ce.ToString())
            Console.WriteLine()
        Next ce
    Else
        Console.WriteLine("Source {0} built into {1} successfully.", _
            sourceFile, cr.PathToAssembly)
    End If

    ' Return the results of compilation.
    If cr.Errors.Count > 0 Then
        Return False
    Else
        Return True
    End If
End Function

초기 지원이 있는 언어

.NET은 C#, Visual Basic, C++, JScript 언어에 대한 코드 컴파일러 및 코드 생성기를 제공합니다. 언어별 코드 생성기 및 코드 컴파일러를 구현하면 CodeDOM 지원을 다른 언어로 확장할 수 있습니다.

참고 항목