Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/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
Templates 获取Groovy闭包正文文本_Templates_Groovy_Metaprogramming_Template Meta Programming - Fatal编程技术网

Templates 获取Groovy闭包正文文本

Templates 获取Groovy闭包正文文本,templates,groovy,metaprogramming,template-meta-programming,Templates,Groovy,Metaprogramming,Template Meta Programming,我正在尝试动态创建Groovy类。我正在使用GroovyClassLoader和SimpleTemplateEngine注入字段和方法定义,生成新的类文本表示,并将其传递给GroovyClassLoader.parseClass()。这适用于类字段,如果表示方法体的闭包作为文本注入,也适用于方法。我的问题是,我不知道如何将Groovy闭包转换为它的文本表示。我在StackOverflow上找到了几个例子: 及 但这两个例子都给了我一个例外: Caught: java.lang.NullPoi

我正在尝试动态创建Groovy类。我正在使用GroovyClassLoader和SimpleTemplateEngine注入字段和方法定义,生成新的类文本表示,并将其传递给GroovyClassLoader.parseClass()。这适用于类字段,如果表示方法体的闭包作为文本注入,也适用于方法。我的问题是,我不知道如何将Groovy闭包转换为它的文本表示。我在StackOverflow上找到了几个例子:

但这两个例子都给了我一个例外:

Caught: java.lang.NullPointerException: Cannot invoke method getDeclaredMethods() on null object
这意味着metaClass.classNode为空

这是我的剧本:

c1 = '{return p1 + p2}'
c2 = '{return p1 * p2}'
data = [fields: ['p1': 'int', 'p2':'int'], methods: ['m1': c1, 'm2':c2], name: 'Agent']

templateText = '''

class $name
{
<%fields.each {%>    $it.value $it.key \n<% } %>
<%methods.each {%>   def $it.key() $it.value \n<% } %> 
}


'''

engine = new groovy.text.SimpleTemplateEngine()
template = engine.createTemplate(templateText)
result = template.make(data)
println result

GroovyClassLoader loader = new GroovyClassLoader()
Class cls = loader.parseClass(result.toString())
i = cls.newInstance()
i.p1 = 1
i.p2 = 2
i.setP2(10)
println i.m1()
println i.m2()
c1='{返回p1+p2}'
c2='{返回p1*p2}'
数据=[字段:['p1':'int',p2':'int'],方法:['m1':c1',m2':c2],名称:'Agent']
templateText=“”
类$name
{
$it.value$it.key\n
def$it.key()$it.value\n
}
'''
engine=new groovy.text.SimpleTemplateEngine()
template=engine.createTemplate(templateText)
结果=模板.make(数据)
打印结果
GroovyClassLoader=新的GroovyClassLoader()
类cls=loader.parseClass(result.toString())
i=cls.newInstance()
i、 p1=1
i、 p2=2
i、 setP2(10)
println i.m1()
println i.m2()

使用您链接到的第二个示例,我可以(我认为)实现这一点:

导入groovy.inspect.swingui.AstNodeToScriptVisitor
字符串方法(闭包a){
使用{writer->
a、 元类.classNode.getDeclaredMethods(“doCall”)[0]。代码。访问新的AstNodeToScriptVisitor(编写器)
“{${writer.toString()}}”
}
}
c1={p1+p2}
c2='{返回p1*p2}'
数据=[字段:['p1':'int',p2':'int'],方法:['m1':方法(c1),'m2':c2],名称:“代理”]
templateText=“”
类$name
{
$it.value$it.key\n
def$it.key()$it.value\n
}
'''
engine=new groovy.text.SimpleTemplateEngine()
template=engine.createTemplate(templateText)
结果=模板.make(数据)
打印结果
GroovyClassLoader=新的GroovyClassLoader()
类cls=loader.parseClass(result.toString())
i=cls.newInstance()
i、 p1=1
i、 p2=2
i、 setP2(10)
println i.m1()
println i.m2()

它在GroovyConsole中不起作用,但如果您将其保存为脚本,并从命令行调用它,它就会起作用,该脚本对我有效。。。您使用的是什么版本的Groovy?或者你试图做的脚本中没有失败的地方吗?@tim_yates脚本按原样工作,但是如果我省略了闭包周围的单引号,比如c1={return p1+p2},脚本会抛出一个异常。首先,你的代码给了我相同的NullPointerException,通过将您的方法作为类成员,我成功地使它工作,现在它工作得很好。谢谢你的努力。你能发布一个你所做的工作的样本吗?
import groovy.inspect.swingui.AstNodeToScriptVisitor

String method( Closure a ) {
  new StringWriter().with { writer ->
    a.metaClass.classNode.getDeclaredMethods("doCall")[0].code.visit new AstNodeToScriptVisitor( writer )
    "{${writer.toString()}}"
  }
}

c1 = {p1 + p2}
c2 = '{return p1 * p2}'
data = [fields: ['p1': 'int', 'p2':'int'], methods: ['m1': method( c1 ), 'm2':c2], name: 'Agent']

templateText = '''

class $name
{
<%fields.each {%>    $it.value $it.key \n<% } %>
<%methods.each {%>   def $it.key() $it.value \n<% } %> 
}


'''

engine = new groovy.text.SimpleTemplateEngine()
template = engine.createTemplate(templateText)
result = template.make(data)
println result

GroovyClassLoader loader = new GroovyClassLoader()
Class cls = loader.parseClass(result.toString())
i = cls.newInstance()
i.p1 = 1
i.p2 = 2
i.setP2(10)
println i.m1()
println i.m2()