【问题标题】:Groovy DSL with embedded groovy scripts带有嵌入式 groovy 脚本的 Groovy DSL
【发布时间】:2011-12-13 19:28:01
【问题描述】:

我正在编写一个 DSL 用于在 groovy 中表达流(我知道的原创)。我想为用户提供编写在流程中某些点存储和评估的函数的能力。比如:

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

现在,我很确定我可以用引号括住闭包并存储它。但如果可能的话,我想在编辑这些 DSL 时保持语法高亮和内容辅助。我意识到闭包可以引用来自周围流定义的工件,当在不同的上下文中执行闭包时,这些工件将不再有效,我对此很好。实际上,我想将闭包语法用于非闭包函数定义。

tl;博士;我需要在评估 DSL 时获取闭包的代码,以便将其存储在数据库中并稍后由脚本宿主执行。

【问题讨论】:

    标签: reflection groovy dsl


    【解决方案1】:

    我认为没有办法获取闭包的源代码,因为这些信息在编译过程中会被丢弃。或许您可以尝试编写一个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,这是一个专门为启用序列化闭包并稍后执行它们而创建的库,可能在远程机器上。试试看,也许这就是你需要的。

    【讨论】:

    • 很好的答案,谢谢!如果没有预建的 AST 渲染库,这个答案会胜出,但我会给它更多时间让其他人回答。
    猜你喜欢
    • 2012-07-10
    • 2011-05-13
    • 2011-09-06
    • 2022-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多