代码之家  ›  专栏  ›  技术社区  ›  MarkSh

将对象实例传递给Roslyn ScriptEngine

  •  10
  • MarkSh  · 技术社区  · 11 年前

    我正在寻找一个C#脚本引擎,它可以解释C#代码块,同时维护上下文。例如,如果输入: var a = 1; ,然后 a + 3 ,它将输出 4 . 我知道MS Roslyn ,它确实做到了这一点,但这是一个沙盒(相对于启动它的程序)。因此,如果我创建 ScriptEngine 以及 MyClass (只是我的一个业余班),我没有办法通过 my_class script_engine .

    有没有可能 传递该引用 ?

    什么 我想 要做的是:

    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() 是缺失的部分,因为罗斯林中没有这样的功能。

    2 回复  |  直到 11 年前
        1
  •  12
  •   andyp    11 年前

    答案在 link @Herman评论道。

    事实证明,罗斯琳 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); 
    
        2
  •  0
  •   Tone Å koda    11 年前

    下面是如何将变量从对象传递到roslyn动态执行代码的完整过程。还包括eval()包装器。 首先从microsoft.com安装RoslynSetup.exe http://www.microsoft.com/en-sa/download/details.aspx?id=34685

    然后将引用Roslyn.Compilers和Roslyn.Ccompilers.CSharp添加到项目(程序集/扩展)

    以下是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);            
            }
        }
    }