生成源代码和在 CodeDOM 图中编译程序

更新:2007 年 11 月

System.CodeDom.Compiler 命名空间提供了从 CodeDOM 对象图生成源代码和用受支持的编译器管理编译的接口。代码生成器可以按照 CodeDOM 图,用某种编程语言生成源代码。从 CodeDomProvider 派生的类通常可以提供一些方法,用于生成和编译提供程序支持的语言的代码。

使用 CodeDOM 代码生成器生成源代码

要用某种语言生成源代码,需要一个表示要生成的源代码的结构的 CodeDOM 图。

下面的示例演示如何创建 CSharpCodeProvider 的实例:

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

代码生成图通常包含在 CodeCompileUnit 中。若要为包含 CodeDOM 图的 CodeCompileUnit 生成代码,请调用代码提供程序的 GenerateCodeFromCompileUnit 方法。此方法有一个可用来生成源代码的 TextWriter 参数,因此,有时需要首先创建一个可以写入的 TextWriter。下面的示例演示了如何从 CodeCompileUnit 生成代码以及如何将生成的源代码写入名为 HelloWorld.cs 的文件。

Public Shared Function GenerateCSharpCode( _
    compileunit As CodeCompileUnit) As String
       
    ' Generate the code with the C# code provider.
    Dim provider As CSharpCodeProvider = New CSharpCodeProvider()

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

    ' Create a TextWriter to a StreamWriter to an output file.
    Dim tw As New IndentedTextWriter( _
        New StreamWriter(sourceFile, False), "    ")

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

    ' Close the output file.
    tw.Close()
        
    Return sourceFile
End Function
   
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.
    IndentedTextWriter tw = new IndentedTextWriter(
            new StreamWriter(sourceFile, false), "    ");
            
    // Generate source code using the code provider.
    provider.GenerateCodeFromCompileUnit(compileunit, tw, 
            new CodeGeneratorOptions());

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

    return sourceFile;
}
   

使用 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 Shared Function CompileCSharpCode(sourceFile As String, _
    exeFile As String) As Boolean
    Dim provider As CSharpCodeProvider = New CSharpCodeProvider()
          
    ' Build the parameters for source compilation.
    Dim cp As New CompilerParameters()
         
    ' Add an assembly reference.
    cp.ReferencedAssemblies.Add("System.dll")

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

    ' Generate an executable instead of a class library.
    cp.GenerateExecutable = True
          
    ' Set the assembly file name to generate.
    cp.OutputAssembly = exeFile
        
    ' 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)
        Dim ce As System.CodeDom.Compiler.CompilerError
        For Each ce 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
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;
    }
}

原本即受支持的语言

.NET Framework 为下列语言提供了代码编译器和代码生成器:C#、Visual Basic、C++、J# 和 JScript。通过实现专用于特定语言的代码生成器和代码编译器,CodeDOM 支持可以扩展到其他语言。

请参见

参考

CodeDOM 快速参考

System.CodeDom

System.CodeDom.Compiler

其他资源

高级开发技术