Compilation et réflection

Soyez le premier à donner votre avis sur cette source.

Snippet vu 6 368 fois - Téléchargée 15 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

Messages postés
253
Date d'inscription
vendredi 13 juin 2003
Statut
Membre
Dernière intervention
18 mai 2009

oki :)
Messages postés
186
Date d'inscription
lundi 11 mars 2002
Statut
Membre
Dernière intervention
30 novembre 2010
2
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.
Messages postés
253
Date d'inscription
vendredi 13 juin 2003
Statut
Membre
Dernière intervention
18 mai 2009

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 :/
Messages postés
186
Date d'inscription
lundi 11 mars 2002
Statut
Membre
Dernière intervention
30 novembre 2010
2
* 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.
Messages postés
149
Date d'inscription
mercredi 23 juillet 2003
Statut
Membre
Dernière intervention
30 janvier 2009

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.