2011-12-13 133 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