Partager via


Génération du code source et compilation d'un programme à partir d'un graphique CodeDOM

L'espace de noms System.CodeDom.Compiler fournit des interfaces pour la génération du code source à partir des graphiques d'objets CodeDOM et la gestion de la compilation avec les compilateurs pris en charge. Un fournisseur de code peut produire du code source dans un langage de programmation particulier conformément à un graphique CodeDOM. Une classe qui dérive de CodeDomProvider peut fournir en général des méthodes pour générer et compiler le code pour le langage pris en charge par le fournisseur.

Utilisation d'un fournisseur de code CodeDOM pour générer du code source

Pour générer du code source dans un langage particulier, il vous faut un graphique CodeDOM représentant la structure du code source à générer.

L'exemple suivant montre comment créer une instance d'un CSharpCodeProvider :

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

Le graphique de génération du code est généralement contenu dans CodeCompileUnit. Pour générer le code d'un CodeCompileUnit qui contient un graphique CodeDOM, appelez la méthode GenerateCodeFromCompileUnit du fournisseur de code. Cette méthode possède un paramètre pour TextWriter qu'elle utilise afin de générer le code source ; il est donc parfois nécessaire de créer d'abord un TextWriter dans lequel il est possible d'écrire. L'exemple suivant illustre la génération de code à partir de CodeCompileUnit et l'écriture du code source généré dans un fichier appelé HelloWorld.cs.

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
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:
    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;
    }

Utilisation d'un fournisseur de code CodeDOM pour compiler des assemblys

Appel de la compilation

Pour compiler un assembly à l'aide d'un fournisseur CodeDom, vous devez disposer soit du code source à compiler dans un langage pour lequel vous avez un compilateur, soit d'un graphique CodeDOM à partir duquel le code source à compiler peut être généré.

Si vous compilez un graphique CodeDOM, passez le CodeCompileUnit contenant le graphique à la méthode CompileAssemblyFromDom du fournisseur de code. Si vous avez un fichier de code source dans un langage que le compilateur comprend, passez le nom du fichier contenant le code source à la méthode CompileAssemblyFromFile du fournisseur CodeDom. Vous pouvez également passer une chaîne contenant le code source dans un langage que le compilateur comprend à la méthode CompileAssemblyFromSource du fournisseur CodeDom.

Configuration des paramètres de compilation

Toutes les méthodes invoquant une compilation standard d'un fournisseur CodeDom ont un paramètre de type CompilerParameters qui indique les options à utiliser pour la compilation.

Vous pouvez spécifier un nom de fichier pour l'assembly de sortie dans la propriété OutputAssembly de CompilerParameters. Sinon, un nom de fichier de sortie par défaut est utilisé.

Par défaut, un nouveau CompilerParameters est initialisé dont la propriété GenerateExecutable est définie avec la valeur false. Si vous compilez un programme exécutable, vous devez assigner à la propriété GenerateExecutable la valeur true. Lorsque GenerateExecutable a la valeur false, le compilateur génère une bibliothèque de classes.

Si vous compilez un exécutable à partir d'un graphique CodeDOM, un CodeEntryPointMethod doit être défini dans le graphe. S'il existe plusieurs points d'entrée dans le code, il sera peut-être nécessaire de définir la propriété MainClass de CompilerParameters en lui assignant le nom de la classe qui définit le point d'entrée à utiliser.

Pour inclure des informations de débogage dans un exécutable généré, assignez à la propriété IncludeDebugInformation la valeur true.

Si votre projet référence des assemblys, vous devez spécifier les noms d'assemblys en tant qu'éléments de StringCollection comme la propriété ReferencedAssemblies du CompilerParameters que vous utilisez pour appeler la compilation.

Vous pouvez compiler un assembly écrit en mémoire plutôt que sur disque en affectant la valeur true à la propriété GenerateInMemory. Lorsqu'un assembly est généré en mémoire, votre code peut obtenir une référence à l'assembly généré à partir de la propriété CompiledAssembly de CompilerResults. Lorsqu'un assembly est écrit sur disque, vous pouvez obtenir le chemin d'accès à cet assembly à partir de la propriété PathToAssembly de CompilerResults.

Pour spécifier une chaîne d'arguments de ligne de commande personnalisés à utiliser lors de l'appel du processus de compilation, affectez cette chaîne à la propriété CompilerOptions.

Si l'appel du processus de compilation requiert un jeton de sécurité Win32, spécifiez le jeton dans la propriété UserToken.

Pour lier un fichier de ressources Win32 dans l'assembly compilé, spécifiez son nom dans la propriété Win32Resource.

Pour spécifier le niveau d'avertissement auquel la compilation doit être interrompue, assignez à la propriété WarningLevel un entier correspondant au niveau d'avertissement auquel la compilation s'arrête. Il est également possible de configurer le compilateur de manière à ce qu'il interrompe la compilation en cas d'avertissements, en affectant à la propriété TreatWarningsAsErrors la valeur true.

L'exemple de code suivant montre la compilation d'un fichier source à l'aide d'un fournisseur CodeDom dérivé de la classe CodeDomProvider.

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
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:
    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;
        }
    }

Langages avec prise en charge initiale

Le .NET Framework fournit des compilateurs de code et des générateurs de code pour les langages suivants : C#, Visual Basic, C++, J# et JScript. La prise en charge de CodeDOM peut être étendue à d'autres langages en implémentant des générateurs de code et des compilateurs de code spécifiques au langage.

Voir aussi

Référence

Aide-mémoire de CodeDOM

System.CodeDom

System.CodeDom.Compiler

Autres ressources

Génération et compilation de code source dynamique