Compilation et réflection

5/5 (7 avis)

Snippet vu 6 866 fois - Téléchargée 17 fois

Contenu du snippet

Un petit d exemple d utilisation du compilateur C# de .net.
J'en avais besoin pour une appli alors si ca peu vous faire gagner de temps...
Le code source est dans une chaine, il est compilé en mémoire.
Si la compilation réussi, on exécute le point d entrée avec paramètres, puis une méthode de test avec paramètres.
Si la compilation échoue, on affiche les erreurs.
Au passage, ca fait un petit exemple d utilisation de la réflexion en .Net

Source / Exemple :


using System;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text;

namespace cscomp
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            // Code source a compiler
            StringBuilder oSource = new StringBuilder();
            oSource
            .AppendLine("using System.Windows.Forms;")
            .AppendLine("namespace nsTest")
            .AppendLine("{")
            .AppendLine(" public static class Program")
            .AppendLine(" {")
            .AppendLine("  public static void Main()")
            .AppendLine("  {")
            .AppendLine("   MessageBox.Show(\"Hello !!\");")
            .AppendLine("  }")
            .AppendLine("  public static void Test(object args)")
            .AppendLine("  {")
            .AppendLine("   MessageBox.Show(\"Test :'\" + args.ToString() + \"'\");")
            .AppendLine("  }")
            .AppendLine(" }")
            .AppendLine("}");
            
            // Instanciation du compilateur et des ses paramètres
            CodeDomProvider oCodeProvider = new Microsoft.CSharp.CSharpCodeProvider();
            CompilerParameters oCompPrms = new CompilerParameters();

            // Définition des références
            oCompPrms.ReferencedAssemblies.Add("System.dll");
            oCompPrms.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            
            // Paramètres non utilisé
            //oCompPrms.EmbeddedResources.Clear();
            //oCompPrms.LinkedResources.Clear();
            //oCompPrms.TempFiles.Clear(); 
            //oCompPrms.UserToken = new IntPtr(0);
            //oCompPrms.Win32Resource = "";
            //oCompPrms.OutputAssembly = "nsTest";
            //oCompPrms.CompilerOptions  = string.Empty;
            //oCompPrms.Evidence = null;
            
            //  Définition des paramètres de compilation
            oCompPrms.GenerateExecutable = true;
            oCompPrms.GenerateInMemory = true;
            oCompPrms.IncludeDebugInformation = false;
            oCompPrms.TreatWarningsAsErrors  = true;
            oCompPrms.MainClass = "nsTest.Program";
            oCompPrms.WarningLevel = 3;

            // Compilation du code
            CompilerResults oCompResults 
                = oCodeProvider.CompileAssemblyFromSource
                (oCompPrms, new string[] { oSource.ToString() });

            //  Si compilation réussie
            if (oCompResults.NativeCompilerReturnValue == 0)
            {
                // Lecture de l'assembly compilé
                Assembly oAssembly = oCompResults.CompiledAssembly;
    
                // Invocation du point d'entrée (Main)
                object oRunResult = oAssembly.EntryPoint.Invoke(null, null);
                
                // Invocation de la méthode test
                Type oType = oAssembly.GetType("nsTest.Program");
                MethodInfo oMethod = oType.GetMethod("Test", new Type[]{ typeof(object) });
                oMethod.Invoke(null, new object[] { "toto" });
            }

            // Si erreur de compilation
            else
            {
                // Affichage des erreurs
                foreach (CompilerError oCompError in oCompResults.Errors)
                {
                    string sCompError = string.Format
                    (
                        "{0} (l:{1},c:{2}) '{3}' ({4}):{5}",
                        (oCompError.IsWarning) ? "warning" : "error",
                        oCompError.Line.ToString(), oCompError.Column.ToString(),
                        oCompError.FileName,
                        oCompError.ErrorNumber, oCompError.ErrorText
                    );
                    System.Diagnostics.Debug.WriteLine(sCompError);
                }
            }

        }

    }

}

Conclusion :


Pour tester, créer un nouveau projet winform, et copier le code dans la classe program.

A voir également

Ajouter un commentaire Commentaires
lakichemole Messages postés 253 Date d'inscription vendredi 13 juin 2003 Statut Membre Dernière intervention 18 mai 2009
30 janv. 2009 à 15:43
oki :)
thiosyiasar Messages postés 186 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 30 novembre 2010 3
30 janv. 2009 à 15:35
Si j'ai compris :), c'est vrai que j'aurais pu détecter les using du code, mais je préfère un exemple le plus simple possible.
lakichemole Messages postés 253 Date d'inscription vendredi 13 juin 2003 Statut Membre Dernière intervention 18 mai 2009
30 janv. 2009 à 15:22
Non en fait se que je voulais dire c'est que tu aurais pu parcourir ton code en récupérant tous les using et après pour chaque using récupéré ba tu rajoute ta ligne un truc du genre:
foreach string using in ListUsingTrouve
{
oCompPrms.ReferencedAssemblies.Add(using);
}
ça rendrais plus générique si bien que pour rajouter un using tu n'a qu'a le faire dans ta partie code (version string)
Je sais pas si je em fait comprendre :/
thiosyiasar Messages postés 186 Date d'inscription lundi 11 mars 2002 Statut Membre Dernière intervention 30 novembre 2010 3
30 janv. 2009 à 15:05
* On peut générer un exe ? oui
oCompPrms.GenerateExecutable = true;
oCompPrms.GenerateInMemory = false;
* Utilité ?
Dans mon cas, une application ou l'utilisateur peut ajouter certaines fonctionnalité avec du code C#.
* System de plugins ?
On utilise des interfaces dans l'application, et la réflexion(objet Activator) pour définir l'implémentation dans une dll qui implémente ces interfaces.
oximoron Messages postés 149 Date d'inscription mercredi 23 juillet 2003 Statut Membre Dernière intervention 30 janvier 2009
30 janv. 2009 à 13:26
Merci, c'est clair et concis peut être un peu trop ;) je me pose quand même quelques questions : On peut générer un exe avec la compilation à la volé ? Dans quels cas c'est utile (car on peut vite faire des trucs bien crados) ? Un système de plugin (développés par des tiers pour une appli) marche de cette façon ?
Afficher les 7 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.