【问题标题】:Get a Groovy closure body text获取 Groovy 闭包正文
【发布时间】:2014-04-28 08:31:00
【问题描述】:

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

print the closure definition/source in Groovy

Getting the contents of closure, in groovy

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

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()

【问题讨论】:

  • 该脚本对我有用...您使用的是什么版本的 Groovy?还是您尝试执行的脚本中没有某些内容失败了?
  • @tim_yates 脚本按原样工作,但如果我像这样 c1 = {return p1 + p2} 在我的闭包周围省略单引号,脚本会抛出异常

标签: templates groovy metaprogramming template-meta-programming


【解决方案1】:

使用您链接到的第二个示例,我可以(我认为)工作:

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()

它在 GroovyConsole 中不起作用,但如果将其保存为脚本并从命令行调用它,它就会起作用

【讨论】:

  • 起初你的代码给了我同样的 NullPointerException,我设法通过将你的方法作为类成员让它工作,现在它工作得很好。感谢您的努力。
  • 你能发布一个你所做的工作的样本吗?
猜你喜欢
  • 2013-05-22
  • 1970-01-01
  • 2014-10-15
  • 2014-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
相关资源
最近更新 更多