2010-01-21 66 views
5

是否有可能在C#中编写一个简单且快速的函数,该函数将执行字符串中的任意方法?例如,如果我设置了MyString =“MessageBox.Show(”Some Message“)”,然后调用ExecuteString(MyString),则会弹出一个消息框,其中包含“Some Message”。C#:执行存储在字符串变量中的函数

(我可能已经在上面的代码做一些错误我还不知道C#。我试图评估它是否会为一个特定的项目是适当的。)

+2

不知道这是一个重复的,但你可能会寻找一种方式来在C#REPL,并有一个很好的问题关于这里:http://stackoverflow.com/questions/1038106/或在这里http://stackoverflow.com/questions/2058715/它可能提供一些想法/源代码。 – 2010-01-21 05:35:26

回答

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

你其实可以。我不仅发布了如何,而且还自己做了。 – 2010-01-21 05:34:41

+1

我没有说这不是_possible_,只是它不是_easy_。我不确定您提到的MSDN示例 - 需要超过100行来“执行”一行代码,请注意 - 可以被认为很容易。 – 2010-01-21 05:37:43

3

您应该能够利用这一点,换到运行一个字符串转换成所需的代码一个函数。

基本上你在做的是将一小段C#代码包装在Program.Main样式函数中,引用一些程序集的基本功能(可能包括你自己的程序集),然后在内存中运行已编译的程序。

这可能比您需要运行一行或两行代码的开销多一点。

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

+0

同意 - 最好的选择是将这类工作委托给IronPython或IronRuby,这样做更容易。 – 2010-01-21 05:36:02

+0

是的,对于如此少量的“脚本代码”使用基于脚本的轻量级方法会更好。 – 2010-01-21 05:38:17

+0

如果需要上下文,例如从代码字符串访问主机应用程序中的运行时变量和类比IronPython或其他DLR语言好得多或者如果代码字符串更改经常比编译汇编不是一个好选择,无论如何,因为您将创建一个汇编每个需要评估的代码字符串。 – affan 2010-01-21 05:43:10

相关问题