Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
IDynamicMetaObjectProvider动态对象和JScript.Net_Dynamic_C# 4.0_Javascript - Fatal编程技术网

IDynamicMetaObjectProvider动态对象和JScript.Net

IDynamicMetaObjectProvider动态对象和JScript.Net,dynamic,c#-4.0,javascript,Dynamic,C# 4.0,Javascript,我有一个名为EcmaEval的类,它允许我的应用程序的用户执行任意javascript。这个类的实现在这个问题的末尾。我允许用户访问一个“环境”对象,该对象提供对他们编写脚本有用的方法和属性 问题是我需要向JScript公开一个C#动态对象,但它不起作用。以前有人这样做过吗?应该这样做吗 所以,如果我有一个普通的旧对象,它有一个名为name的字符串属性,那么它可以工作: test test = new test(); test.Name = "Daniel Bry

我有一个名为EcmaEval的类,它允许我的应用程序的用户执行任意javascript。这个类的实现在这个问题的末尾。我允许用户访问一个“环境”对象,该对象提供对他们编写脚本有用的方法和属性

问题是我需要向JScript公开一个C#动态对象,但它不起作用。以前有人这样做过吗?应该这样做吗

所以,如果我有一个普通的旧对象,它有一个名为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);
test test=新测试();
test.Name=“Daniel Bryars”;
EcmaEval EcmaEval=新的EcmaEval(新列表
{
Assembly.GetExecutionGassembly()位置
},测试);
字符串ecma=“environment.Name”;
字符串结果=ecmaEval.Eval(ecma);
断言.AreEqual(“Daniel Bryars”,结果);
但如果我将EcmaEval对象传递给动态对象,则它不会(属性名为null):

dynamic expandoObject=new expandoObject();
expandoObject.Name=“Daniel Bryars”;
EcmaEval EcmaEval=新的EcmaEval(新列表
{
Assembly.GetExecutionGassembly()位置
},扩展对象);
字符串ecma=“environment.Name”;
字符串结果=ecmaEval.Eval(ecma);
断言.AreEqual(“Daniel Bryars”,结果);
(结果为空。)

下面是EcmaEval的实现。还有另一个类称为JSObjectToDotNetConversion,它将JSObjects强制为C#object(它使用反射来创建C#object并设置字段和/或属性),但该类的实现并不相关

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);
        }
    }
}
使用系统;
使用System.CodeDom.Compiler;
使用System.Collections.Generic;
运用系统反思;
使用Microsoft.JScript;
命名空间Aeriandi.ApplicationBlocks.BusinessBaseObjects.Ecma
{
/// 
///将JScrip eval函数作为.net方法公开。
///这将使用“安全”JScript.Eval,因此不允许访问磁盘或网络。
/// 
公共类EcmaEval
{
私有只读对象\u计算器;
私有只读类型_evaluatorType;
私有只读对象\u环境;
public EcmaEval():此(新列表(),null)
{            
}
公共EcmaEval(列出引用的程序集、对象环境)
{
if(null==referencedAssembly)
{
抛出新ArgumentNullException(“ReferencedAssemblys”,“参数ReferencedAssemblys不能为null”);
}
_环境=环境;
JScriptCodeProvider编译器=新的JScriptCodeProvider();
CompilerParameters参数=新的CompilerParameters();
parameters.GenerateInMemory=true;
foreach(referencedAssembly中的字符串referencedAssembly)
{
parameters.referencedAssembly.Add(referencedAssembly);
}
字符串源=
@“包评估器
{
班级评估员
{
公共函数Eval(表达式:字符串,环境:对象)
{ 
返回值(expr);
}
}
}";
CompilerResults results=compiler.compileasemblyFromSource(参数,_jscriptSource);
Assembly=结果。已编译的Assembly;
_evaluatorType=assembly.GetType(“Evaluator.Evaluator”);
_evaluator=Activator.CreateInstance(\u evaluatorType);
}
公共对象Eval(返回类型,字符串ecmaScript)
{
ecmaScript=包装括号(ecmaScript);
对象结果=_evalutorType.InvokeMember(
“评估”,
BindingFlags.InvokeMethod,
无效的
_评估员,
新对象[]{ecmaScript,_environment}
);
返回JSObjectToDotNetConversion.胁迫(返回类型,结果);
}
公共T Eval(字符串ecmaScript)
{
返回(T)Eval(类型(T),ecmaScript);
}
私有静态字符串Wrapin括号(字符串ecmaScript)
{
//您不能用{启动js块,因为它是不明确的(根据规范)
//所以我们把所有的东西都放在括号里。
返回String.Format(“({0})”,ecmaScript);
}
}
}

基本上,使用JScript.Net似乎无法做到这一点。我想我需要使用在DLR上构建的东西,如:

铁匠

托管JScript(不再由MS开发)

这里有关于托管JScript及其消亡的更多信息:

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);
        }
    }
}