2014-07-14 49 views
9

我正在尋找一個C#腳本引擎,可以解釋的C#代碼塊,而維修器材的上下文。例如,如果輸入:var a = 1;,然後輸入a + 3,它將輸出4。 我知道MS Roslyn,它確實是這樣做的,但它是一個沙箱(尊重啓動它的程序)。所以,如果我創建的ScriptEngine實例和MyClass實例(只是一個arbirary類礦井),我沒有選擇的my_class參考傳遞給script_engine通行證對象實例的羅斯林的ScriptEngine

是否有可能以某種方式通引用

我想什麼做的,是一樣的東西:

ScriptEngine engine; // A Roslyn object 
Session session // A Roslyn object 

MyClass my_class; // My object 

// all required initializations 

Submission<object> sm = session.CompileSubmission<object>("var a=1;"); 
dynamic result = sm.Execute(); 

Submission<object> sm = session.CompileSubmission<object>("a + 3;"); 
dynamic result = sm.Execute(); // result is now 4 

MyClass my_class; 
session.AddReferenceToAnOject(my_class); // function that does not exists, but reflect my intention 

Submission<object> sm = session.CompileSubmission<object>("my_class.ToString();"); 
dynamic result = sm.Execute(); // result is no the output of my_class.ToString() 

請注意AddReferenceToAnOject()是缺少的一部分,有羅斯林沒有這樣的功能。

+1

如果我是你,我會刪除第二個項目符號點。這將有助於防止您的問題被作爲「關於工具,圖書館或最喜愛的非現場資源的建議」而關閉。 –

+0

看看CS-腳本http://www.csscript.net/ – Mez

+1

或許檢查[與宿主應用程序進行交互(http://blogs.msdn.com/b/csharpfaq/archive/2011/12/02 /introduction-to-the-roslyn-scripting-api.aspx)。 – Herman

回答

10

答案由@Herman評論一link被發現。

當它變成,羅斯林ScriptEngine/Session支持Host Object的概念。 爲了使用它,定義一個你的選擇類,並在創建會話時傳遞它。這樣做,使該主機對象的所有公共成員,提供給會話中的上下文:

public class MyHostObject 
{ 
    public List<int> list_of_ints; 
    public int an_int = 23; 
} 

var hostObject = new MyHostObject(); 
hostObject.list_of_ints = new List<int>(); 
hostObject.list_of_ints.Add(2); 
var engine = new ScriptEngine(new[] { hostObject.GetType().Assembly.Location }); 

// passing reference to hostObject upon session creation 
var session = Session.Create(hostObject); 

// prints `24` to console 
engine.Execute(@"System.Console.WriteLine(an_int + list_of_ints.Count);", 
       session); 
0

下面是一個完整的過程如何從對象傳遞變量羅斯林動態執行的代碼。包括也是eval()包裝。 首先從microsoft.com http://www.microsoft.com/en-sa/download/details.aspx?id=34685

參考Roslyn.Compilers和Roslyn.Compilers.CSharp然後添加到您的項目(組件/擴展)安裝RoslynSetup.exe

這裏是在vs2012 C#控制檯應用程序,完整的工作代碼。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Roslyn.Compilers; 
using Roslyn.Compilers.CSharp; 
using Roslyn.Scripting; 
using Roslyn.Scripting.CSharp; 

namespace testRoslyn 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      TestRoslyn tr = new TestRoslyn(); 
      tr.Test = "this was set from main program "; 
      tr.test(); 
      System.Console.WriteLine(tr.Test); 
      tr.Test = "this was set from main program for eval"; 
      Eval e = new Eval(); 
      e.create<TestRoslyn>(tr);       
      e.eval("Test = Test + \" AND THIS WAS SET FROM Eval()\";"); 
      System.Console.WriteLine(tr.Test); 
      string a = e.eval<string>("string a = \"return this from eval\";a"); 
      System.Console.WriteLine(a); 
      tr.Test = "now return this"; 
      string b = e.eval<string>("string a = Test + \" ... and this\";a"); 
      System.Console.WriteLine(b); 
      double d = e.eval<double>("double dbl = 1.2345*3;dbl"); 
      System.Console.WriteLine(d); 
      e.eval("string testIt(string a){return \"testIt(): \"+a+\"\";}"); 
      string c = e.eval<string>("string c = testIt(\"nice\");c"); 
      System.Console.WriteLine(c); 
      Console.ReadKey(); 
     } 
    } 

    public class TestRoslyn 
    { 
     public string Test; 

     public TestRoslyn() 
     { 
     } 

     public string test() 
     { 
      ScriptEngine roslynEngine = new ScriptEngine(); 
      Roslyn.Scripting.Session session = roslynEngine.CreateSession(this); 
      session.AddReference(this.GetType().Assembly); 
      session.AddReference("System.Web"); 
      session.ImportNamespace("System"); 
      session.ImportNamespace("System.Web"); 
      var result = (string)session.Execute("Test = Test + \" ... and this was set from roslyn code.\";Test"); 
      return result; 
     } 
    } 

    public class Eval 
    { 
     ScriptEngine RoslynEngine = new ScriptEngine(); 
     Roslyn.Scripting.Session Session; 

     public void create<T>(T hostObject = null) where T : class 
     { 
      RoslynEngine = new ScriptEngine(); 
      Session = RoslynEngine.CreateSession(hostObject); 
      if (hostObject != null) 
       Session.AddReference(hostObject.GetType().Assembly); 
      Session.AddReference("System.Web"); 
      Session.ImportNamespace("System"); 
      Session.ImportNamespace("System.Web"); 
     } 

     public void eval (string strEval) 
     {             
      Session.Execute(strEval); 
     } 

     public T eval<T>(string strEval) 
     { 
      return (T) Session.Execute(strEval);    
     } 
    } 
}