3

我想知道如何从与 DSL 一起使用的闭包中调用闭包。例如,让我们RestBuilder以 Grails 的插件为例。

想象一下,我连续有几个块,例如:

rest.post("http://my.domain/url") {
    auth(username, password)
    contentType "text/xml"
    body someContent
}

...唯一改变的是someContent. 每次调用都会auth重复contentTypebody所以我想做类似的事情:

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并按照DSL中的定义进行访问。有没有办法通过设置所有者、代表等来做到这一点?toWrapauthcontentTypeRestBuilder

(注意:我在上面的示例中了解到,我可以只声明一个以 URL + 内容作为参数的函数,然后rest.post在函数内调用。我的问题更笼统——我希望了解该语言,并且我可以更广泛地应用功能技术。)

4

2 回答 2

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
})
于 2013-08-27T15:32:03.263 回答
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))
}

每次都克隆闭包可以防止过时状态,并且对值进行柯里化会将它们缓存在闭包中,以便它们在被 Rest 构建器调用时可用。

于 2013-08-27T04:44:42.243 回答