我想知道如何从一个与DSL一起使用的闭包中调用一个闭包。例如,让我们使用Grails的RestBuilder
插件。
想象一下,我连续几个街区如:
rest.post("http://my.domain/url") {
auth(username, password)
contentType "text/xml"
body someContent
}
...唯一改变的是someContent
。每次调用auth
和contentType
以及body
都会重复。所以我想做点什么:
def oauth = [clientId: 'c', clientSecret: 's']
def withAuth(Closure toWrap) {
Closure wrapped = { it ->
auth(oauth.clientId, oauth.clientSecret)
contentType "text/xml"
toWrap.call()
}
return wrapped
}
rest.post("http://my.domain/url") (withAuth {
body someContent
})
现在,我希望wrapped
和toWrap
能够访问auth
DSL中定义的contentType
和RestBuilder
。有没有办法通过设置所有者,代表等来实现这一目标?
(注意:我在上面的例子中理解,我可以声明一个以URL +内容为参数的函数,只需在函数内调用rest.post
。我的问题更为通用 - 我是我希望能够更广泛地应用语言和功能技术。)
答案 0 :(得分:3)
感谢@ igor-artamonov,我有以下工作方法。请注意,我将withAuth
从函数更改为闭包,以便它可以访问脚本级状态而无需在脚本上声明@Field
变量。
def oauth = [clientId: 'c', clientSecret: 's']
def withAuth { Closure toWrap ->
return {
auth(oauth.clientId, oauth.clientSecret)
contentType "text/xml"
toWrap.delegate = delegate
toWrap.call()
}
}
rest.post("http://my.domain/url", withAuth {
body someContent
})
答案 1 :(得分:1)
您可以利用foo(params) { ... }
的语法是foo(params, { ... })
的语法糖这一事实:
def c = { oauth, b ->
auth(oauth.clientId, oauth.clientSecret)
contentType "text/xml"
body b
}
...
def doPost(String body) {
rest.post("http://my.domain/url", c.clone().curry(oauth, body))
}
每次克隆闭包都会阻止过时状态,并且currying值会将它们缓存在闭包中,以便它们在Rest构建器调用时可用。