2012-10-31 36 views
2

讓我們考慮一個簡單的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的getProperty實施Closure

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中的10個屬性名稱?

回答

1

這是一個黑客位,但這應該得到你想要的東西,而不會改變的Groovy來源:

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

    def dslDelegate = new MyDslDelegate(owner: 'IncCorp', payee: 'TheBoss') 
    [email protected] = 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,這意味着你實施的任何黑客可能會在未來的版本中停止工作。

也許這個問題會更有意義,如果你解釋了爲什麼你願意提供賞金和尋找繞開這個問題的方法,而不僅僅是改變名稱到不同的地方,並完全避免這個問題。保留的符號是一種語言的一個非常基本的限制,有試圖解決它們似乎是非常不明智的。