2010-08-22 73 views
1

我有一個名爲EcmaEval的類,它允許我的應用程序用戶執行任意的javascript。這個課程的實施是在這個問題的最後。我允許用戶訪問一個「環境」對象,該對象提供的方法和屬性對他們來說是非常有用的。IDynamicMetaObjectProvider動態對象和JScript.Net

問題是我需要將C#動態對象暴露給JScript,但它不起作用。有沒有人做過這個 - 它應該工作嗎?

所以,如果我有一個普通的老對象與字符串屬性名爲name它的工作原理:

 test test = new test(); 
     test.Name = "Daniel Bryars"; 

     EcmaEval ecmaEval = new EcmaEval(new List<String> 
              { 
               Assembly.GetExecutingAssembly().Location 
              }, test); 

     String ecma = "environment.Name"; 
     String result = ecmaEval.Eval<String>(ecma); 

     Assert.AreEqual("Daniel Bryars", result); 

,但如果我把我的EcmaEval對象動態對象則不會(屬性名稱爲null):

 dynamic expandoObject = new ExpandoObject(); 
     expandoObject.Name = "Daniel Bryars"; 

     EcmaEval ecmaEval = new EcmaEval(new List<String> 
              { 
               Assembly.GetExecutingAssembly().Location 
              }, expandoObject); 

     String ecma = "environment.Name"; 
     String result = ecmaEval.Eval<String>(ecma); 
      Assert.AreEqual("Daniel Bryars", result); 

(結果爲null)

這裏的EcmaEval實施。還有另一個涉及JSObjectToDotNetConversion的類,它將JSObjects強制轉換爲C#對象(它使用反射來創建C#對象並設置字段和/或屬性),但該類的實現不相關。

using System; 
using System.CodeDom.Compiler; 
using System.Collections.Generic; 
using System.Reflection; 
using Microsoft.JScript; 

namespace Aeriandi.ApplicationBlocks.BusinessBaseObjects.Ecma 
{ 
    /// <summary> 
    /// Exposes the JScrip eval function as a .net method. 
    /// This uses the "safe" JScript.Eval so no disk, or network access is allowed. 
    /// </summary> 
    public class EcmaEval 
    { 
     private readonly object _evaluator; 
     private readonly Type _evaluatorType; 
     private readonly Object _environment; 

     public EcmaEval() : this (new List<string>(), null) 
     {    
     } 

     public EcmaEval(List<String> referencedAssemblies, Object environment) 
     { 
      if (null == referencedAssemblies) 
      { 
       throw new ArgumentNullException("referencedAssemblies", "The argument referencedAssemblies must not be null"); 
      } 

      _environment = environment; 
      JScriptCodeProvider compiler = new JScriptCodeProvider(); 

      CompilerParameters parameters = new CompilerParameters(); 
      parameters.GenerateInMemory = true; 

      foreach (String referencedAssembly in referencedAssemblies) 
      { 
       parameters.ReferencedAssemblies.Add(referencedAssembly); 
      } 

      string _jscriptSource = 
@"package Evaluator 
{ 
    class Evaluator 
    { 
     public function Eval(expr : String, environment : Object) 
     { 
      return eval(expr); 
     } 
    } 
}"; 
      CompilerResults results = compiler.CompileAssemblyFromSource(parameters, _jscriptSource); 

      Assembly assembly = results.CompiledAssembly; 
      _evaluatorType = assembly.GetType("Evaluator.Evaluator"); 
      _evaluator = Activator.CreateInstance(_evaluatorType); 
     } 

     public Object Eval(Type returnType, String ecmaScript) 
     { 
      ecmaScript = WrapInBrackets(ecmaScript); 

      Object result = _evaluatorType.InvokeMember(
        "Eval", 
        BindingFlags.InvokeMethod, 
        null, 
        _evaluator, 
        new object[] { ecmaScript, _environment } 
       ); 

      return JSObjectToDotNetConversion.Coerce(returnType, result); 
     } 

     public T Eval<T>(String ecmaScript) 
     { 
      return (T) Eval(typeof (T), ecmaScript); 
     } 

     private static String WrapInBrackets(String ecmaScript) 
     { 
      //You can't start a block of js with a { because it's ambiguous (according to the spec) 
      //so we wrap everything in brackets. 
      return String.Format("({0})", ecmaScript); 
     } 
    } 
} 

回答

0

Bascially它看起來像我不能使用JScript.Net做到這一點。我想我需要使用內置ontop的的DLR的喜歡的東西:

IronJS

http://github.com/fholm/IronJS

管理的JScript(這是不再由MS開發的。)

http://www.microsoft.com/downloads/details.aspx?familyid=A5189BCB-EF81-4C12-9733-E294D13A58E6&displaylang=en

還有一些關於Managed JScript的更多信息,它在這裏消失:http://pietschsoft.com/post/2009/06/12/Managed-JScript-on-the-DLR-from-Microsoft-is-DEAD-Why.aspx