2010-01-21 9 views
5

Est-il possible d'écrire une fonction simple et rapide en C# qui exécutera des méthodes arbitraires à partir d'une chaîne? Par exemple, si je mets MyString = "MessageBox.Show (" Some Message ")", puis appelez ExecuteString (MyString), une boîte de message apparaîtra avec "Some Message" dedans.C#: exécute une fonction stockée dans une variable de chaîne

(je l'ai probablement fait une sorte d'erreur dans le code ci-dessus, je ne sais pas encore C#,. Je suis en train d'évaluer s'il serait approprié pour un projet spécifique.)

+2

Je ne sais pas si cela est un double, mais vous êtes à la recherche sans doute un moyen de la rempl en C#, et il y a une bonne question à ce sujet ici: http://stackoverflow.com/questions/1038106/ ou ici http://stackoverflow.com/questions/2058715/ qui peut offrir quelques idées/code source. –

Répondre

2

Hélas, C# n'est pas un langage dynamique de cette manière. Vous ne pouvez pas vraiment le faire facilement, et si c'est vraiment quelque chose que vous devez faire, pensez à utiliser un langage .Net plus en ligne avec vos besoins, comme IronPython ou IronRuby.

Votre meilleure alternative disponible est d'utiliser l'espace de noms CodeDom, comme cet exemple vraiment alambiqué et odieux de this forum thread montre:

using System; 
using System.CodeDom; 
using System.CodeDom.Compiler; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Drawing; 
using System.Linq; 
using System.Reflection; 
using System.Reflection.Emit; 
using System.Text; 
using System.Windows.Forms; 

namespace TestApp 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     SampleLib.SampleType test = new SampleLib.SampleType(); 

     private void button1_Click(object sender, EventArgs e) 
     { 
      // Dynamically build and call the method 
      label1.Text = test.MyText; 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      StringBuilder DynamicCode = new StringBuilder(); 
      DynamicCode.Append("namespace TestDynamic"); 
      DynamicCode.Append("{"); 
      DynamicCode.Append("public class DynamicCode"); 
      DynamicCode.Append("{"); 
      DynamicCode.Append("public static void EditText(SampleLib.SampleType t)"); 
      DynamicCode.Append("{"); 
      DynamicCode.Append("t.MyText = \"Goodbye!\";"); 
      DynamicCode.Append("}"); 
      DynamicCode.Append("}"); 
      DynamicCode.Append("}"); 

      string CodeString = DynamicCode.ToString(); 

      System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath); 
      CodeDomProvider provider = CodeDomProvider.CreateProvider("C#"); 
      CompilerParameters CompileParams = new CompilerParameters(new string[] { fi.DirectoryName + "\\SampleLib.dll" }, 
       fi.DirectoryName + "\\Dynamic.dll"); 
      CompileParams.MainClass = "DynamicCode"; 
      CompileParams.GenerateExecutable = false; 
      //CompileParams.GenerateInMemory = true; 
      CompilerResults r = provider.CompileAssemblyFromSource(CompileParams, new string[] {CodeString}); 
      foreach (CompilerError er in r.Errors) 
      { 
       Console.WriteLine(er.ErrorText); 
      } 
     } 

     private void button3_Click(object sender, EventArgs e) 
     { 
      // Dynamically call assembly 
      System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath); 
      Assembly dynAsm = Assembly.LoadFile(fi.DirectoryName + "\\Dynamic.dll"); 
      if (dynAsm != null) 
      { 
       object o = dynAsm.CreateInstance("TestDynamic.DynamicCode", true); 
       Type t = dynAsm.GetType("TestDynamic.DynamicCode"); 
       t.GetMethod("EditText").Invoke(o, new object[]{test}); 
      } 
     } 
    } 
} 
+0

Vous pouvez réellement. Je n'ai pas seulement posté comment, mais je l'ai fait moi-même. –

+1

Je n'ai pas dit que ce n'était pas _possible_, juste que ce n'était pas _easy_. Je ne suis pas sûr que l'exemple MSDN que vous mentionnez - qui nécessite plus de 100 lignes pour «exécuter» une seule ligne de code, pensez-vous - pourrait être considéré comme facile. –

3

Vous devriez pouvoir utiliser et envelopper le code requis pour exécuter une chaîne en une fonction. Essentiellement ce que vous faites est d'encapsuler le petit peu de code C# dans une fonction de style Program.Main, référençant certains assemblages pour des fonctionnalités de base (peut-être y compris votre propre assemblage), puis exécutez le programme compilé en mémoire.

Il est probable qu'il y ait un peu plus de frais généraux que nécessaire pour exécuter simplement une ou deux lignes de code.

http://support.microsoft.com/kb/304655

+0

D'accord - la meilleure alternative est vraiment de déléguer ce genre de travail à IronPython ou IronRuby, où c'est beaucoup plus facile à faire. –

+0

Oui, il serait préférable d'utiliser des méthodes basées sur des scripts légers pour de si petites quantités de "code de script". –

+0

Si un contexte est requis, par exemple l'accès aux variables d'exécution et aux classes dans l'application hôte de ironPython ou d'autres langages DLR est bien meilleur Ou si la chaîne de code change souvent que compiler assembly n'est pas une bonne option de toute façon assembly pour chaque chaîne de code nécessitant une évaluation. – affan

Questions connexes