2011-12-13 136 views
2

我正在寫groovy表達流(原來我知道)的DSL。我想讓用戶能夠編寫在流程中的某些點存儲和評估的函數。例如:groovy DSL與嵌入groovy腳本

states { 
    "checkedState" { 
     onEnter {state-> 
      //do some groovy things with state object 
     } 
    } 
} 

現在,我很確定我可以用引號括住閉包並存儲它。但是,如果可能的話,編輯這些DSL時,我想保持語法突出顯示和內容幫助。我意識到閉包可能會引用來自周圍流定義的工件,當在不同的上下文中執行閉包時,該工件將不再有效,並且我對此很滿意。實際上,我想用非閉包函數定義的閉包語法。

tl; dr;我需要在評估DSL時獲取閉包的代碼,以便它可以存儲在數據庫中,稍後由腳本主機執行。

回答

2

我不認爲有一種方法可以獲得閉包的源代碼,因爲這些信息在編譯過程中被丟棄了。也許你可以嘗試編寫一個AST transformation,它可以在運行時使閉包的語法樹可用。

如果您只關心將閉包存儲在數據庫中,並且您不需要以後訪問源代碼,則可以嘗試序列化並存儲序列化表單。

Closure實現Serializable和歸零其ownerthisObjectdelegate屬性後,我才得以序列化,但我得到的反序列化ClassNotFoundException

def myClosure = {a, b -> a + b} 

Closure.metaClass.setAttribute(myClosure, "owner", null) 
Closure.metaClass.setAttribute(myClosure, "thisObject", null) 
myClosure.delegate = null 

def byteOS = new ByteArrayOutputStream() 
new ObjectOutputStream(byteOS).writeObject(myClosure) 
def serializedClosure = byteOS.toByteArray() 

def input = new ObjectInputStream(new ByteArrayInputStream(serializedClosure)) 
def deserializedClosure = input.readObject() // throws CNFE 

經過一番搜索,我發現Groovy Remote Control,專門創建,使序列化封閉和後來執行它們,可能是遠程計算機上的庫。試試看,也許這就是你需要的。

+0

偉大的答案謝謝!如果缺少預先構建的AST渲染庫,這個答案將會勝出,但我會給它多一點時間讓其他人回答。 – 2011-12-15 18:10:08