gpt4 book ai didi

dynamic - IDynamicMetaObjectProvider 动态对象和 JScript.Net

转载 作者:行者123 更新时间:2023-11-28 10:29:16 25 4
gpt4 key购买 nike

我有一个名为 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);

但是如果我将 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);

(结果为空。)

这里是EcmaEval的实现。还有另一个名为 JSObjectToDotNetConversion 的类,它将 JSObject 强制转换为 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);
}
}
}

最佳答案

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

IronJS

http://github.com/fholm/IronJS

托管 JScript(MS 不再开发。)

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

有一些关于托管 JScript 的更多信息,它的消亡在这里:http://pietschsoft.com/post/2009/06/12/Managed-JScript-on-the-DLR-from-Microsoft-is-DEAD-Why.aspx

关于dynamic - IDynamicMetaObjectProvider 动态对象和 JScript.Net,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3541459/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com