首页 文章

在Groovy DSL中使用'owner'属性

提问于
浏览
2

我们来考虑一个简单的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 值,因为 Closure 的Groovy getProperty 实现

public Object getProperty(final String property) {
    if ("delegate".equals(property)) {
        return getDelegate();
    } else if ("owner".equals(property)) {
        return getOwner();
    ...
    } else {
        switch(resolveStrategy) {
            case DELEGATE_FIRST:
        ...
    }

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

2 回答

  • 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

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

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

相关问题