2010-01-21 7 views
5

Можно ли написать простую и быструю функцию в C#, которая будет выполнять произвольные методы из строки? Например, если я устанавливаю MyString = «MessageBox.Show (« Некоторое сообщение »)», а затем вызывается ExecuteString (MyString), в нем появляется сообщение «Some Message».C#: выполнить функцию, хранящуюся в строковой переменной

(я, вероятно, сделал какие-то ошибки в коде выше я пока не знаю C#,. Я пытаюсь оценить, будет ли это уместно для конкретного проекта.)

+2

Не уверен, если это дубликат, но вы, вероятно, ищет способ, чтобы Repl в C#, и есть хороший вопрос об этом здесь: http://stackoverflow.com/questions/1038106/ или здесь http://stackoverflow.com/questions/2058715/, который может предложить некоторые идеи/исходный код. –

ответ

2

Увы, Таким образом, C# не является динамическим языком. Вы не можете сделать это легко, и если вам действительно нужно что-то сделать, подумайте об использовании языка .Net в соответствии с вашими потребностями, например IronPython или IronRuby.

Ваш лучший доступный вариант заключается в использовании пространства имен CodeDOM, так как это действительно извилистый и отвратительные, например, из this forum thread шоу:

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

Вы на самом деле можете. Я не только опубликовал, но и сделал это сам. –

+1

Я не сказал, что это не возможно, просто, что это не было _easy_. Я не уверен, что пример MSDN, о котором вы говорите, который требует более 100 строк для «выполнения» одной строки кода, заметьте, - можно считать легким. –

3

Вы должны быть в состоянии использовать это и перенесите код, необходимый для запуска строки в функция.

По существу, вы делаете перенос маленького бита кода C# в функцию стиля Program.Main, ссылаясь на некоторые сборки для базовых функций (возможно, включая собственную сборку), а затем запустите скомпилированную программу в памяти.

Это, скорее всего, немного больше накладных расходов, чем вам нужно просто запустить одну или две строки кода.

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

+0

Согласовано - лучшая альтернатива - это действительно делегировать эту работу IronPython или IronRuby, где это намного проще сделать. –

+0

Да, было бы лучше использовать легкие скриптовые методы для таких небольших количеств «кода сценария». –

+0

Если необходим контекст, например, доступ к переменным среды выполнения и классам в хост-приложении из строки кода, чем у IronPython или других языков DLR, намного лучше, или если строка кода изменяется часто, чем сборка сборки, это не очень хороший вариант, поскольку вы создадите сборку для каждой строки кода, которая нуждается в оценке. – affan

Смежные вопросы