有没有一种好的方法可以将GroovyDSL构建器的一部分提取到变量或帮助函数中,以便可以重用它们?

7lrncoxx  于 8个月前  发布在  其他
关注(0)|答案(1)|浏览(60)

下面是一个用于声明电子邮件的构建器风格GroovyDSL的最小示例。

email {
    from("[email protected]")
    to("[email protected]")
    body {
        html("Ahoj")
        // lots of other fields here
    }
}

例如,我想提取身体部位

body {
        html("Ahoj")
        // lots of other fields here
    }

并在多封邮件中重复使用也许它应该看起来像这样

email {
    from("[email protected]")
    to("[email protected]")
    myBody("Ahoj1")
}

email {
    from("[email protected]")
    to("[email protected]")
    myBody("Ahoj2")
}

我想在myBody函数中保留IDE自动完成功能。

/// This is the (abbreviated) DSL example from
///  http://docs.groovy-lang.org/docs/latest/html/documentation/core-domain-specific-languages.html#TheDelegatesToannotation-DelegatesTo

def email(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = EmailSpec) Closure cl) {
    def email = new EmailSpec()
    def code = cl.rehydrate(email, this, this)
    code.resolveStrategy = Closure.DELEGATE_ONLY
    code()
}

class EmailSpec {
    void from(String from) { println "From: $from" }
    void to(String... to) { println "To: $to" }

    void body(@DelegatesTo(strategy = Closure.DELEGATE_ONLY, value = BodySpec) Closure body) {
        def bodySpec = new BodySpec()
        def code = body.rehydrate(bodySpec, this, this)
        code.resolveStrategy = Closure.DELEGATE_ONLY
        code()
    }
}

class BodySpec {
    void html(String html) { println "Body (html): $html" }
}

我使用上面的DSL使问题自包含。事实上,我有兴趣用Jenkins Job DSL做同样的事情。

2j4z5cfb

2j4z5cfb1#

创建一个helper函数

static <V> Closure<V> closureCtx(@DelegatesTo.Target context, @DelegatesTo Closure<V> closure) {
    return closure
}

然后使用它为提取的DSL片段设置上下文

Closure<Void> myBody(String text) {
    return closureCtx(EmailSpec) { ->
        body {
            html(text)
            // lots of other fields here
        }
    }
}

这足以使IDE自动完成功能在编辑片段时正常工作。

相关问题