2010-01-21 25 views
5

¿Es posible escribir una función simple y rápida en C# que ejecutará métodos arbitrarios desde una cadena? Por ejemplo, si configuro MyString = "MessageBox.Show (" Some Message ")" y luego llamo ExecuteString (MyString), aparecerá un cuadro de mensaje con "Some Message" en él.C#: ejecuta una función almacenada en una variable de cadena

(probablemente he hecho algún tipo de error en el código anterior que todavía no sé C#;. Estoy tratando de evaluar si sería apropiado para un proyecto específico.)

+2

No estoy seguro si esto es un duplicado, pero lo más probable está buscando una manera de que rEPL en C#, y hay una buena pregunta sobre eso aquí: http://stackoverflow.com/questions/1038106/ o aquí http://stackoverflow.com/questions/2058715/ que puede ofrecer algunas ideas/código fuente. –

Respuesta

2

Por desgracia, C# no es un lenguaje dinámico de esa manera. Realmente no puedes hacer esto fácilmente, y si realmente es algo que tienes que hacer, considera usar un lenguaje .Net más acorde con tus necesidades, como IronPython o IronRuby.

Su mejor alternativa disponible es utilizar el espacio de nombres CodeDom, como este ejemplo verdaderamente complicado y atroz de this forum thread espectáculos:

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

Usted realmente puede. No solo publiqué cómo, sino que también lo hice yo mismo. –

+1

No dije que no fuera posible, simplemente que no era fácil. No estoy seguro de que el ejemplo de MSDN que menciona, que requiere más de 100 líneas para "ejecutar" una sola línea de código, tenga en cuenta, podría considerarse fácil. –

3

Usted debe ser capaz de utilizar esto y ajustar el código necesario para ejecutar una cadena en Una función.

Esencialmente lo que está haciendo es envolver el pequeño código C# en una función de estilo Program.Main, haciendo referencia a algunos ensambles para funcionalidad básica (tal vez incluyendo su propio ensamblaje) luego ejecute el programa compilado en la memoria.

Es probable que tenga que cargar un poco más de lo necesario para ejecutar una o dos líneas de código.

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

+0

Estoy de acuerdo: la mejor alternativa es delegar este tipo de trabajo a IronPython o IronRuby, donde es mucho más fácil hacerlo. –

+0

Sí, sería mejor utilizar métodos ligeros basados ​​en scripts para cantidades tan pequeñas de "código de secuencia de comandos". –

+0

Si se requiere un contexto, por ejemplo, acceso a variables de tiempo de ejecución y clases en la aplicación de host de la cadena de código que ironPython u otros lenguajes DLR es mucho mejor O si la cadena de código cambia a menudo, el ensamblaje no es una buena opción, ya que creará montaje para cada cadena de código que necesita evaluación. – affan

Cuestiones relacionadas