将一个使用JavaScript作为用户脚本的C#项目移植到Java中时,有一个类有一个重载方法:
public class TreeNode {
public TreeNode GetChild(int index) { ... }
public TreeNode GetChild(String childName) { ... }
public TreeNode GetChild(String targetAttributeName, String targetAttributeValue) { ... }
...
}
使用Rhino,我可以通过以下方式在Java和JavaScript之间进行对象桥接:
ScriptableObject.putProperty(scope, "TreeNode", Context.javaToJS(new TreeNode(), scope));
对于简单地调用函数的脚本,这样做非常有效(所有重载函数将正确地解析为正确的类型)。然而,C#应用程序还会索引到TreeNode中。例如,JavaScript用户函数是:
function NumericButtonClick() {
screen = TreeNode.FindNodeById("Screen");
screen["Text"] = screen["Text"] + Source["Text"];
}
运行这段JavaScript代码会得到预期的结果:
在线程“AWT-EventQueue-0”中,异常org.mozilla.javascript.EvaluatorException:Java类“TreeNode”没有公共实例字段或名为“Text”的方法。
要修复此问题,Rhino通过允许您实现
Scriptable
接口(或扩展包含一些常见样板代码的ScriptableObject
)来支持此功能。在执行此操作后,绑定似乎消失了。Exception in thread "AWT-EventQueue-0" org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object.
调试代码时,具体交互是Rhino对Scriptable
的get()
方法作了四次调用:
get(name = "FindNodeByID")
get(name = "__noSuckMethod__")
get(name = "toString")
get(name = "valueOf")
为了解决这个问题,我们可以创建特定的
FunctionObject
对象,让Rhino知道FindNodeByID是一段Java代码中的函数。(虽然我也试过手动创建,但只使用Scriptable.defineFunctionProperties
可以用更少的代码自动完成。) 直到我们遇到重载的GetChild函数时,才会出现以下异常:org.mozilla.javascript.EvaluatorException: Method "GetChild" occurs multiple times in class "TreeNode".
或者,ScriptableObject.defineClass(scope, TreeNode.class)
将会将 jsFunction_*
函数映射到 JavaScript 中。然而,这也会生成相同类型的错误:
org.mozilla.javascript.EvaluatorException: Invalid method "jsFunction_GetChild": name "GetChild" is already in use.
最后,我尝试在
get()
内部添加逻辑,以尝试选择我们想要并将其返回到Rhino中的 FunctionObject
。然而,你没有提供任何函数参数化或预测的方法,除非使用一种非常混乱的方式。
我是否遗漏了什么?有没有办法同时索引Rhino中映射的Java对象和具有重载Java函数?Rhino显然都支持,肯定支持它们一起使用,但是似乎不明显如何做到这一点。
感谢任何想法!