在Groovy DSL中使用“owner”属性

时间:2012-10-31 06:18:38

标签: groovy dsl

让我们考虑一个简单的Groovy DSL

execute {
    sendNotification owner
    sendNotification payee
}

执行是

public static void execute(Closure dslCode) {
    Closure clonedCode = dslCode.clone()
    def dslDelegate = new MyDslDelegate(owner:  'IncCorp', payee: 'TheBoss')

    clonedCode.delegate = dslDelegate
    clonedCode.call()
}

和自定义委托是

public static class MyDslDelegate {
    def owner
    def payee

    void sendNotification(to) {
        println "Notification sent to $to"
    }
}

运行execute块的预期结果是

Notification sent to IncCorp
Notification sent to TheBoss

实际的是

Notification sent to class package.OwnerClassName
Notification sent to TheBoss

问题是owner是Groovy Closure本身的保留属性,没有resolveStrategy选项有助于将owner值替换为来自委托的自定义值,因为Groovy { {1}}

的{1}}实施
getProperty

我的问题是,有人可以如何制定此限制并在自定义DSL中使用Closure属性名称?

2 个答案:

答案 0 :(得分:1)

这有点像黑客,但这应该可以让你得到你想要的东西,而不需要改变Groovy来源:

public static void execute(Closure dslCode) {
    Closure clonedCode = dslCode.clone()

    def dslDelegate = new MyDslDelegate(owner:  'IncCorp', payee: 'TheBoss')
    clonedCode.@owner = dslDelegate.owner
    clonedCode.resolveStrategy = Closure.DELEGATE_ONLY

    clonedCode.delegate = dslDelegate
    clonedCode.call()
}

参考:Is it possible to change the owner of a closure?

答案 1 :(得分:1)

简单的答案是否定的,你不能。 'owner'是Groovy中的保留关键字,因此根据定义不能用作任意符号。即使有办法解决这个问题,你最好只使用一个与语言实现不冲突的名称 - 在Groovy中尤其如此,它一直有望完全重新设计其MOP,意思是你实施的任何黑客都可能在将来的版本中停止工作。

如果您解释为什么您愿意提供赏金并寻找解决此问题的方法,而不是仅仅将名称更改为不同的东西并完全避免问题,那么问题可能更有意义。保留符号是语言的一个非常基本的限制,并且试图解决它们似乎是非常不明智的。