这类似于Need Groovy syntax help for generating a Closure from a String,但有点复杂:
我正在使用我无法控制的复杂DSL(Jenkins Job DSL,特别是,但是为了清晰起见我使用的是假设的DSL)并且我将我的代码分解为返回的闭包。在此代码中不以“my”开头的所有闭包都是假设的DSL:
//scriptContext is a reference to the original script as this is a util class
static def myMethod(def scriptContext) {
//everything here comes from some hypothetical DSL
scriptContext.diningTable() {
....
fruits myCreateFruitsClosure()
....
}
}
static def myCreateFruitsClosure() {
return {
apple('Gala') {
seed("brown")
shape {
funky()
dimpled()
}
}
}
}
以上工作正常。
现在让我们说我希望动态指定apple的详细信息并从某个地方加载一些groovy代码(例如,XML)。
现在我有:
// I pass in the script context for the binding
static def myCreateFruitsClosure(def scriptContext) {
return {
apple('Gala') {
// This comes from somewhere in real life:
def code = """seed("blue"); shape { oval() ; cardioid() }"""
def evalWrapper = new GroovyShell(context.binding).evaluate(' { -> ' + code + '}')
evalWrapper()
}
}
}
我得到“没有签名方法:Script1.seed()”显然,seed()方法在不使用eval时确实存在,因为它之前有效,所以我的上下文/范围是错误的
我试过了:
所有这些产生的误差略有不同。什么是正确的方式?
答案 0 :(得分:2)
最终我的工作:
结果如下:
static def myCreateFruitsClosure() {
return {
apple {
def code = """
L:{
self.seed("blue")
self.shape {
oval()
cardioid()
}
}"""
// sometimes "self: delegate" is appropriate instead of this:
new GroovyShell(new Binding([self: owner])).evaluate(code)
}
}
}
我想这比我想做的更简单。注意" L:"强制evaluate()将代码视为开放代码块而不是闭包。
如果有人有更好的方法,请告诉我,但这很有效。