Compartilhar via


Gerar e compilar código-fonte a partir de um fraph CodeDOM

O namespace System.CodeDom.Compiler fornece interfaces para geração de código-fonte de grafos de objeto CodeDOM e para o gerenciamento da compilação com compiladores com suporte. Um provedor de código pode produzir código-fonte em uma linguagem de programação específica acordo com um grafo CodeDOM. Uma classe que deriva de CodeDomProvider normalmente pode fornecer métodos para gerar e compilar o código para a linguagem à qual o provedor dá suporte.

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

Para gerar o código-fonte em uma determinada linguagem, você precisa de um grafo CodeDOM que representa a estrutura do código-fonte a ser gerada.

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 geralmente está contido em um CodeCompileUnit. Para gerar código para um CodeCompileUnit que contém um gráfico CodeDOM, chame o método GenerateCodeFromCompileUnit do provedor de código. Esse método possui um parâmetro para um TextWriter que ele usa para gerar o código-fonte, portanto, às vezes é necessário criar primeiro um TextWriter no qual possa ser gravado. O exemplo a seguir demonstra a geração de código a partir 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

Use um provedor de código CodeDOM para compilar assemblies

Invocar compilação

Para compilar um assembly usando um provedor de CodeDom, você deve ter o código-fonte para compilar em uma linguagem para a qual tenha um compilador ou um grafo CodeDOM do qual o código-fonte pode ser gerado.

Se você estiver compilando de um grafo CodeDOM, passe o CodeCompileUnit que contém o grafo para o método CompileAssemblyFromDom do provedor de código. Se você tiver um arquivo de código-fonte em uma linguagem que o compilador compreende, passe o nome do arquivo que contém o código-fonte para o método CompileAssemblyFromFile do provedor de CodeDom. Você também pode passar uma cadeia de caracteres que contém o código-fonte em uma linguagem que o compilador compreende para o método CompileAssemblyFromSource do provedor de CodeDom.

Configurar parâmetros de compilação

Todos os métodos padrão de invocar a compilação de um provedor de 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 propriedade OutputAssembly do arquivoCompilerParameters. Caso contrário, um nome de arquivo de saída padrão será usado.

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

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

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

Se o seu projeto fizer referência a quaisquer assemblies, você deverá especificar os nomes dos assemblies como itens em um StringCollection como a propriedade ReferencedAssemblies do CompilerParameters que você usa ao invocar a compilação.

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

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

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

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

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

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

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

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

Confira também