Partilhar via


Gerar e compilar código-fonte a partir de um gráfico CodeDOM

O System.CodeDom.Compiler namespace fornece interfaces para gerar código-fonte a partir de gráficos de objeto CodeDOM e para gerenciar a compilação com compiladores suportados. Um provedor de código pode produzir código-fonte em uma linguagem de programação específica de acordo com um gráfico CodeDOM. Uma classe que deriva de CodeDomProvider pode normalmente fornecer métodos para gerar e compilar código para a linguagem suportada pelo provedor.

Use um provedor de código CodeDOM para gerar código-fonte

Para gerar código-fonte em uma linguagem específica, você precisa de um gráfico CodeDOM que represente a estrutura do código-fonte a ser gerado.

O exemplo a seguir demonstra como criar uma instância de um CSharpCodeProvider:

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

O gráfico para geração de código normalmente está contido em um CodeCompileUnitarquivo . Para gerar código para um CodeCompileUnit que contém um gráfico CodeDOM, chame o GenerateCodeFromCompileUnit método do provedor de código. Este método tem um parâmetro para um TextWriter que ele usa para gerar o código-fonte, por isso, às vezes, é necessário primeiro criar um TextWriter que pode ser gravado. O exemplo a seguir demonstra a geração de código de um CodeCompileUnit e a gravação do código-fonte gerado em um arquivo chamado 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

Usar um provedor de código CodeDOM para compilar assemblies

Invocar compilação

Para compilar um assembly usando um provedor CodeDom, você deve ter o código-fonte para compilar em uma linguagem para a qual você tem um compilador ou um gráfico CodeDOM a partir do qual o código-fonte a ser compilado pode ser gerado.

Se você estiver compilando a partir de um gráfico CodeDOM, passe o CodeCompileUnit gráfico que contém o gráfico para o CompileAssemblyFromDom método do provedor de código. Se você tiver um arquivo de código-fonte em um idioma que o compilador entenda, passe o nome do arquivo que contém o código-fonte para o CompileAssemblyFromFile método do provedor CodeDom. Você também pode passar uma cadeia de caracteres contendo código-fonte em uma linguagem que o compilador entende para o CompileAssemblyFromSource método do provedor CodeDom.

Configurar parâmetros de compilação

Todos os métodos padrão de invocação de compilação de um provedor CodeDom têm um parâmetro do tipo CompilerParameters que indica as opções a serem usadas para compilação.

Você pode especificar um nome de arquivo para o assembly de saída na OutputAssembly propriedade do CompilerParameters. Caso contrário, um nome de arquivo de saída padrão será usado.

Por padrão, um novo CompilerParameters é inicializado com sua GenerateExecutable propriedade definida como false. Se você estiver compilando um programa executável, você deve definir a GenerateExecutable propriedade como true. Quando o GenerateExecutable estiver definido como false, o compilador gerará uma biblioteca de classes.

Se você estiver compilando um executável a partir de um gráfico CodeDOM, um CodeEntryPointMethod deve ser definido no gráfico. Se houver vários pontos de entrada de código, pode ser necessário definir a MainClass propriedade do para o nome da classe que define o ponto de CompilerParameters entrada a ser usado.

Para incluir informações de depuração em um executável gerado, defina a IncludeDebugInformation propriedade como true.

Se seu projeto faz referência a qualquer assembly, você deve especificar os nomes de assembly como itens em a StringCollection como a ReferencedAssemblies propriedade do CompilerParameters que você usa ao invocar compilação.

Você pode compilar um assembly que é gravado na memória em vez de disco definindo a GenerateInMemory propriedade como true. Quando um assembly é gerado na memória, seu código pode obter uma referência ao assembly gerado da CompiledAssembly propriedade de um CompilerResultsarquivo . Se um assembly for gravado no disco, você poderá obter o caminho para o assembly gerado da PathToAssembly propriedade de um CompilerResultsarquivo .

Para especificar uma cadeia de caracteres de argumentos de linha de comando personalizada a ser usada ao invocar o processo de compilação, defina a CompilerOptions cadeia de caracteres na propriedade.

Se um token de segurança Win32 for necessário para invocar o processo do compilador, especifique o UserToken token na propriedade.

Para vincular um arquivo de recurso Win32 ao assembly compilado, especifique o nome do arquivo de recurso Win32 na Win32Resource propriedade.

Para especificar um nível de aviso no qual interromper a compilação, defina a WarningLevel propriedade como um inteiro que representa o nível de aviso no qual a compilação deve ser interrompida. Você também pode configurar o compilador para interromper a compilação se forem encontrados avisos definindo a TreatWarningsAsErrors propriedade como true.

O exemplo de código a seguir demonstra a compilação de um arquivo de origem usando um provedor CodeDom derivado da CodeDomProvider classe.

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

Idiomas com suporte inicial

O .NET fornece compiladores de código e geradores de código para as seguintes linguagens: C#, Visual Basic, C++ e JScript. O suporte ao CodeDOM pode ser estendido a outras linguagens implementando geradores de código e compiladores de código específicos da linguagem.

Consulte também