在基于 Groovy 的 DSL 中绑定的奇怪行为
Strange behaviour with binding in Groovy based DSL
我有一个基于 Groovy 的 DSL,我想在其中访问声明的绑定中的变量。这是我的 DSL 实现:
class Bar {
String barVal
void bar(String bar) {
this.barVal = bar
}
}
class Foo {
Bar bar
void foo(@DelegatesTo(value = Bar, strategy = Closure.DELEGATE_FIRST) closure) {
def bar = new Bar()
def code = closure.rehydrate(bar, null, null)
code()
this.bar = bar
}
}
abstract class MyScript extends Script {
Foo dslEntryPoint(@DelegatesTo(value = Foo, strategy = Closure.DELEGATE_FIRST) closure) {
def foo = new Foo()
def code = closure.rehydrate(foo, null, null)
code()
foo
}
}
这是我的 DSL 示例以及我如何 运行 它:
def DSL_NOT_WORKING = """
dslEntryPoint() {
foo {
bar magicValue
}
}
"""
def DSL_OK = """
def myMagicValue = magicValue
dslEntryPoint() {
foo {
bar myMagicValue
}
}
"""
CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
config.scriptBaseClass = MyScript.class.name
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(getClass().getClassLoader(), config)
Class<Script> clazz = groovyClassLoader.parseClass(DSL_NOT_WORKING)
Binding binding = new Binding()
binding.setVariable('magicValue', '42')
Script script = InvokerHelper.createScript(clazz, binding)
Foo foo = script.run() as Foo
assert foo.bar.barVal == '42'
如您所见,当我将变量与 def
(DSL_OK
) 绑定时,我可以在我的 DSL 中访问它的值,否则 (DSL_NOT_WORKING
) 我会得到一个
java.lang.NullPointerException: Cannot get property 'magicValue' on null object
我做错了什么?如何在没有 def
辅助程序声明的情况下访问变量 magicValue
?我认为这与在我可以传递 this
而不是 null
的闭包上调用 rehydrate
有关,但这似乎不适用于嵌套对象层次结构(Foo->Bar ).
谢谢,
迈克尔
问题是我对 rehydrate
的使用,它用 null
覆盖了所有者和委托。与其在嵌套对象层次结构中记录所有者和委托,不如使用普通委托更简单:
Foo dslEntryPoint(@DelegatesTo(Foo) closure) {
Foo foo = new Foo()
closure.delegate = foo
closure.call()
foo
}
我有一个基于 Groovy 的 DSL,我想在其中访问声明的绑定中的变量。这是我的 DSL 实现:
class Bar {
String barVal
void bar(String bar) {
this.barVal = bar
}
}
class Foo {
Bar bar
void foo(@DelegatesTo(value = Bar, strategy = Closure.DELEGATE_FIRST) closure) {
def bar = new Bar()
def code = closure.rehydrate(bar, null, null)
code()
this.bar = bar
}
}
abstract class MyScript extends Script {
Foo dslEntryPoint(@DelegatesTo(value = Foo, strategy = Closure.DELEGATE_FIRST) closure) {
def foo = new Foo()
def code = closure.rehydrate(foo, null, null)
code()
foo
}
}
这是我的 DSL 示例以及我如何 运行 它:
def DSL_NOT_WORKING = """
dslEntryPoint() {
foo {
bar magicValue
}
}
"""
def DSL_OK = """
def myMagicValue = magicValue
dslEntryPoint() {
foo {
bar myMagicValue
}
}
"""
CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
config.scriptBaseClass = MyScript.class.name
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(getClass().getClassLoader(), config)
Class<Script> clazz = groovyClassLoader.parseClass(DSL_NOT_WORKING)
Binding binding = new Binding()
binding.setVariable('magicValue', '42')
Script script = InvokerHelper.createScript(clazz, binding)
Foo foo = script.run() as Foo
assert foo.bar.barVal == '42'
如您所见,当我将变量与 def
(DSL_OK
) 绑定时,我可以在我的 DSL 中访问它的值,否则 (DSL_NOT_WORKING
) 我会得到一个
java.lang.NullPointerException: Cannot get property 'magicValue' on null object
我做错了什么?如何在没有 def
辅助程序声明的情况下访问变量 magicValue
?我认为这与在我可以传递 this
而不是 null
的闭包上调用 rehydrate
有关,但这似乎不适用于嵌套对象层次结构(Foo->Bar ).
谢谢, 迈克尔
问题是我对 rehydrate
的使用,它用 null
覆盖了所有者和委托。与其在嵌套对象层次结构中记录所有者和委托,不如使用普通委托更简单:
Foo dslEntryPoint(@DelegatesTo(Foo) closure) {
Foo foo = new Foo()
closure.delegate = foo
closure.call()
foo
}