Condividi tramite


Generare e compilare codice sorgente da un grafo CodeDOM

Lo spazio dei nomi System.CodeDom.Compiler offre le interfacce per la generazione di codice sorgente da oggetti grafici CodeDOM e per la gestione della compilazione con i compilatori supportati. Un provider di codice può generare codice sorgente in un determinato linguaggio di programmazione in base a un grafo CodeDOM. Una classe che deriva da CodeDomProvider in genere consente l'uso di metodi per la generazione e la compilazione di codice per il linguaggio supportato dal provider.

Usare un provider di codice CodeDOM per generare il codice sorgente

Per generare codice sorgente in un determinato linguaggio, è necessario un grafo CodeDOM che rappresenti la struttura del codice sorgente da generare.

Nell'esempio seguente viene illustrato come creare un'istanza di CSharpCodeProvider:

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

Il grafo per la generazione di codice è solitamente contenuto in un oggetto CodeCompileUnit. Per generare codice per un CodeCompileUnit oggetto contenente un grafo CodeDOM, chiamare il GenerateCodeFromCompileUnit metodo del provider di codice. Questo metodo ha un parametro per un TextWriter oggetto usato per generare il codice sorgente, quindi a volte è necessario creare prima un TextWriter oggetto in cui scrivere. Nell'esempio seguente viene illustrata la generazione di codice da un CodeCompileUnit oggetto e la scrittura del codice sorgente generato in un file denominato 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

Usare un provider di codice CodeDOM per compilare assembly

Richiamare la compilazione

Per compilare un assembly usando un provider CodeDom, è necessario che il codice sorgente da compilare sia scritto in un linguaggio per il quale è disponibile un compilatore oppure usare un grafo CodeDOM da cui può essere generato il codice da compilare.

Se si esegue la compilazione da un grafo CodeDOM, passare l'oggetto CodeCompileUnit contenente il grafo al metodo CompileAssemblyFromDom del provider di codice. Se si usa un file di codice sorgente in un linguaggio accettato dal compilatore, passare il nome del file contenente il codice sorgente al metodo CompileAssemblyFromFile del provider CodeDom. È anche possibile passare una stringa contenente il codice sorgente in un linguaggio accettato dal compilatore al metodo CompileAssemblyFromSource del provider CodeDom.

Configurare i parametri di compilazione

Tutti i metodi di chiamata della compilazione standard di un provider CodeDom hanno un parametro di tipo CompilerParameters che indica le opzioni da usare per la compilazione.

È possibile specificare un nome file per l'assembly di output nella OutputAssembly proprietà di CompilerParameters. In caso contrario, verrà usato un nome di file di output predefinito.

Per impostazione predefinita, viene inizializzato un nuovo CompilerParameters oggetto con la relativa GenerateExecutable proprietà impostata su false. Se si compila un programma eseguibile, è necessario impostare la GenerateExecutable proprietà su true. GenerateExecutable Quando è impostato su false, il compilatore genererà una libreria di classi.

Se si compila un file eseguibile da un grafo CodeDOM, è necessario definire un oggetto CodeEntryPointMethod nel grafo. Se sono presenti più punti di ingresso del codice, potrebbe essere necessario impostare la MainClass proprietà dell'oggetto CompilerParameters sul nome della classe che definisce il punto di ingresso da usare.

Per includere le informazioni di debug in un eseguibile generato, impostare la IncludeDebugInformation proprietà su true.

Se il progetto fa riferimento a qualsiasi assembly, è necessario specificare i nomi degli assembly come elementi in come StringCollection ReferencedAssemblies proprietà dell'oggetto CompilerParameters utilizzato durante la chiamata alla compilazione.

È possibile compilare un assembly scritto in memoria anziché su disco impostando la GenerateInMemory proprietà su true. Quando un assembly viene generato nella memoria, il codice può ottenere un riferimento all'assembly generato dalla proprietà CompiledAssembly di un oggetto CompilerResults. Se un assembly viene scritto su disco, è possibile ottenere il percorso dell'assembly generato dalla PathToAssembly proprietà di un oggetto CompilerResults.

Per specificare una stringa di argomenti della riga di comando personalizzati da usare quando si richiama il processo di compilazione, impostare la stringa nella proprietà CompilerOptions.

Se è necessario un token di sicurezza Win32 per richiamare il processo di compilazione, specificare il token nella proprietà UserToken.

Per collegare un file di risorse Win32 nell'assembly compilato, specificare il nome del file nella proprietà Win32Resource.

Per specificare un livello di avviso per l'interruzione della compilazione, impostare la proprietà WarningLevel su un intero che rappresenti il livello di avviso in corrispondenza del quale verrà interrotta la compilazione. È anche possibile configurare il compilatore per interrompere la compilazione se vengono rilevati avvisi impostando la TreatWarningsAsErrors proprietà su true.

Nell'esempio di codice seguente viene illustrata la compilazione di un file di origine usando un provider CodeDom derivato dalla 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

Lingue con supporto iniziale

.NET fornisce compilatori di codice e generatori di codice per i linguaggi seguenti: C#, Visual Basic, C++e JScript. Il supporto CodeDOM può essere esteso ad altri linguaggi implementando generatori di codice specifici del linguaggio e compilatori di codice.

Vedi anche