根据 CodeDOM 图生成和编译源代码

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 方法。 此方法有一个可用于生成源代码的 TextWriter 参数,因此,有时需要首先创建一个可以写入的 TextWriter。 下面的示例演示了如何从 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 类型的参数,指示用于编译的选项。

可以在 CompilerParametersOutputAssembly 属性中指定输出程序集的文件名。 否则,将使用默认的输出文件名。

默认情况下,新的 CompilerParameters 在初始化时,其 GenerateExecutable 属性将设置为 false。 如果要编译可执行程序,则必须将 GenerateExecutable 属性设置为 true。 当 GenerateExecutable 设置为 false 时,编译器将生成类库。

如果要从 CodeDOM 图编译可执行文件,则必须在该图中定义 CodeEntryPointMethod。 如果有多个代码入口点,则可能需要将 CompilerParametersMainClass 属性设置为定义要使用的入口点的类名。

若要将调试信息包含在生成的可执行文件中,请将 IncludeDebugInformation 属性设置为 true

如果项目引用了任何程序集,必须将程序集名称指定为 StringCollection 中的项,作为调用编译时使用的 CompilerParametersReferencedAssemblies 属性。

通过将 GenerateInMemory 属性设置为 true,可以编译写入内存而不是磁盘中的程序集。 在内存中生成程序集时,代码可从 CompilerResultsCompiledAssembly 属性中获取对生成的程序集的引用。 如果程序集被写入磁盘,则可从 CompilerResultsPathToAssembly 属性中获取生成的程序集的路径。

若要指定在调用编译进程时使用的自定义命令行参数字符串,请在 CompilerOptions 属性中设置该字符串。

如果在调用编译器进程时需要 Win32 安全令牌,请在 UserToken 属性中指定该令牌。

若要将 Win32 资源文件链接到编译的程序集,请在 Win32Resource 属性中指定该 Win32 资源文件的名称。

若要指定暂停编译的警告等级,请将 WarningLevel 属性设置为一个整数,表示暂停编译的警告等级。 也可以通过将 TreatWarningsAsErrors 属性设置为 true,将编译器配置为在遇到警告时暂停编译。

下面的代码示例演示如何使用从 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 支持可以扩展到其他语言。

请参阅