gpt4 book ai didi

java - 如何通过绑定(bind)映射将对象中某个名称的所有方法绑定(bind)到模板中?

转载 作者:IT老高 更新时间:2023-10-28 21:02:20 25 4
gpt4 key购买 nike

Groovy 模板中的一个正常操作是将命名对象绑定(bind)到模板的范围内,如下所示:

map.put("someObject",object)
template.bind(map)

然后,在模板中我可以像这样引用和使用“someObject”:

someObject.helloWorld()
someObject.helloWorld("Hi Everyone!")
someObject.helloWorld("Hi", "Everyone!")

在模板内部,Groovy 还允许我将方法句柄定义为模板中的一等变量,如下所示:

someObject = someObject.&helloWorld

那么,我可以不引用对象和方法名来做这些:

 someObject() 
someObject("Hello World")
someObject("Hello", "World")

如何在“template.bind(map)”阶段像这样绑定(bind)方法引用,同时自动解析脚本中提供的“.&”运算符等所有参数组合?

使用 MethodClosure 不起作用 - 这是一个简单的测试和我得到的错误

class TestMethodClass {
public void test() {
System.out.println("test()");
}

public void test(Object arg) {
System.out.println("test( " + arg + " )");
}

public void test(Object arg1, Object arg2) {
System.out.println("test( " + arg1 + ", " + arg2 + " )");
}
}

String basic = "<%" +
" def mc1=testInstance.&test;" +
"println \"mc1 class ${mc1.getClass()}\";" +
"println \"mc1 metaclass ${mc1.getMetaClass()}\";" +
"println mc1.getClass();" +
"mc1();" +
"mc1('var1');" +
"mc1('var1', 'var2');" +
"testMethod();" +
" %>";

Map<Object, Object> bindings = new HashMap<>();
bindings.put("testInstance", new TestMethodClass());
bindings.put("testMethod", new MethodClosure(new TestMethodClass(), "test"));

TemplateEngine engine = new GStringTemplateEngine();
Template t = engine.createTemplate(basic);
String result = t.make(bindings).toString();

错误

mc1 class class org.codehaus.groovy.runtime.MethodClosure
mc1 metaclass org.codehaus.groovy.runtime.HandleMetaClass@6069db50[groovy.lang.MetaClassImpl@6069db50[class org.codehaus.groovy.runtime.MethodClosure]]
class org.codehaus.groovy.runtime.MethodClosure
test()
test( var1 )
test( var1, var2 )

groovy.lang.MissingMethodException: No signature of method: groovy.lang.Binding.testMethod() is applicable for argument types: () values: []

一位用户建议我只使用 '.call(..)'

"testMethod.call();" +
"testMethod.call(1);" +
"testMethod.call(1,2);" +

但这违背了目的。在这种情况下,我不妨只绑定(bind)对象而不是“testMethod”,并在常规方法调用的 Groovy 模板中正常使用它。所以这不是这里的解决方案。

该解决方案将创建一个绑定(bind),以便可以像这样调用 testMethod(),并为所有重载方法解析,就像 "mc1=testInstance.&test"提供的那样。

mc1 是 MethodClosure 并且 'mc1=testInstance.&test' 做了一些我想在绑定(bind)阶段做的魔法!

mc1 的元类是一个“HandleMetaClass”。我还可以从 Java 端自定义设置方法闭包的元类。我只想知道如何做到这一点以获得相同的行为。 Groovy 正在模板中执行此操作(从模板解释器中的 Java 端),所以我想提前这样做。

请注意,通常情况下,流媒体模板已经创建了自己的委托(delegate)。当模板代码'def mc1=testInstance.&test;'被解释时,Groovy 编译器/解释器在使用 HandleMetaClass 创建 MethodClosure 时使用该委托(delegate),然后将其安装在现有委托(delegate)中。

正确的答案然后不安装替换委托(delegate),根据下面的@Dany答案,而是与现有委托(delegate)一起使用并创建正确的对象以方便使用 mc1 没有 '.call' 语法。

最佳答案

这将起作用:

"<% " +
"def mc1=testInstance.&test;" +
"mc1();" +
"mc1('var1');" +
"mc1('var1', 'var2');" +
"testMethod.call();" +
"testMethod.call(1);" +
"testMethod.call(1,2);" +
" %>"

testMethod.call(...) 有效,因为它被转换为 getProperty('testMethod').invokeMethod('call', ...)testMethod 属性在绑定(bind)中定义,它是 MethodClosure 类型,其中定义了 call 方法。

然而 testMethod(...) 被翻译成 invokeMethod('testMethod', ...)。它失败了,因为没有定义 testMethod 方法并且你不能通过绑定(bind)来定义它。

编辑

Main.java:

public class Main {
public static void main(String[] args) throws Throwable {
String basic = "<%" +
" def mc1=testInstance.&test;" +
"mc1();" +
"mc1('var1');" +
"mc1('var1', 'var2');" +
"testMethod();" +
"testMethod(1);" +
"testMethod(2,3);" +
" %>";

Map<Object, Object> bindings = new HashMap<>();
bindings.put("testInstance", new TestMethodClass());
bindings.put("testMethod", new MethodClosure(new TestMethodClass(), "test"));

TemplateEngine engine = new GStringTemplateEngine();
Template t = engine.createTemplate(basic);
Closure make = (Closure) t.make();
make.setDelegate(new MyDelegate(bindings));
String result = make.toString();
}
}

MyDelegate.groovy:

class MyDelegate extends Binding {

MyDelegate(Map binding) {
super(binding)
}

def invokeMethod(String name, Object args) {
getProperty(name).call(args)
}
}

MyDelegate.java:

public class MyDelegate extends Binding{

public MyDelegate(Map binding) {
super(binding);
}

public Object invokeMethod(String name, Object args) {
return DefaultGroovyMethods.invokeMethod(getProperty(name), "call", args);
}
}

关于java - 如何通过绑定(bind)映射将对象中某个名称的所有方法绑定(bind)到模板中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41196600/

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