При пренасянето на C# проект към Java, който използва JavaScript за потребителски скриптове, има клас, който има претоварен метод:
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 код води до очакваното Exception in thread "AWT-EventQueue-0" org.mozilla.javascript.EvaluatorException: Java class "TreeNode" has no public instance field or method named "Text".
За да коригира това, Rhino поддържа това, като ви позволява да внедрите интерфейса Scriptable
(или да разширите ScriptableObject
, който съдържа куп общ шаблонен код). След като направите това, обвързването привидно изчезва:
Exception in thread "AWT-EventQueue-0" org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object.
При отстраняване на грешки в кода специфичното взаимодействие е, че Rhino прави четири извиквания към метода get()
на Scriptable
:
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_*
функции в JaavScript. Това обаче генерира същия вид грешка:
org.mozilla.javascript.EvaluatorException: Invalid method "jsFunction_GetChild": name "GetChild" is already in use.
Накрая разгледах добавянето на логика вътре в get()
, за да опитам да избера кое FunctionObject
искаме и да се върна в Rhino. Въпреки това не ви е предоставена никаква параметризация на функцията или някакъв начин да гледате напред, освен по много хакерски, тромав начин.
Изпускам ли нещо? Има ли някакъв начин едновременно да индексирате в картографиран Java обект в Rhino и да имате претоварени Java функции? Rhino очевидно ги подкрепя и двамата и със сигурност ги подкрепя заедно, но не изглежда очевидно как да го направя.
Благодаря за всякакви идеи!