我通过扩展BuilderSupport在Groovy中构建了一个自定义构建器。在配置几乎每个构建器代码示例时,它都能很好地工作:
def builder = new MyBuilder()
builder.foo {
"Some Entry" (property1:value1, property2: value2)
}
这当然是完美的。问题是我不希望我正在构建的信息出现在代码中。我希望将这些信息放在某个文件中,该文件由构建器读入并构建到对象中。我无法弄清楚如何做到这一点。
我甚至无法通过在代码中移动简单条目来完成这项工作。 这有效:
def textClosure = { "Some Entry" (property1:value1, property2: value2) }
builder.foo(textClosure)
因为textClosure是一个闭包。
如果我这样做:
def text = '"Some Entry" (property1:value1, property2: value2)'
def textClosure = { text }
builder.foo(textClosure)
仅为“foo”节点调用构建器。我已经尝试了很多变种,包括将文本块直接传递给构建器而不将其包装在闭包中。它们都会产生相同的结果。
我是否有某种方法可以将一段任意文本传递给我的构建器,以便它能够正确地解析和构建它?
答案 0 :(得分:1)
你的问题是String不是Groovy代码。 ConfigSlurper
处理此问题的方法是使用Script
将文本编译为GroovyClassLoader#parseClass
的实例。如,
// create a Binding subclass that delegates to the builder
class MyBinding extends Binding {
def builder
Object getVariable(String name) {
return { Object... args -> builder.invokeMethod(name,args) }
}
}
// parse the script and run it against the builder
new File("foo.groovy").withInputStream { input ->
Script s = new GroovyClassLoader().parseClass(input).newInstance()
s.binding = new MyBinding(builder:builder)
s.run()
}
Binding的子类只返回一个闭包,用于将调用委托给构建器的所有变量。所以假设foo.groovy包含:
foo {
"Some Entry" (property1:value1, property2: value2)
}
这相当于上面的代码。
答案 1 :(得分:0)
我认为您描述的问题可以通过slurper或解析器更好地解决。
请参阅:
http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlSlurper http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlParser
用于基于XML的示例。
在你的情况下。给定XML文件:
<foo>
<entry name='Some Entry' property1="value1" property2="value2"/>
</foo>
你可以用以下方式啜饮:
def text = new File("test.xml").text
def foo = new XmlSlurper().parseText(text)
def allEntries = foo.entry
allEntries.each {
println it.@name
println it.@property1
println it.@property2
}
答案 2 :(得分:0)
最初,我希望能够指定
"Some Entry" (property1:value1, property2: value2)
在外部文件中。我特别试图避免使用XML和类似XML的语法来使常规用户更容易创建和修改这些文件。我当前的解决方案使用ConfigSlurper
,文件现在看起来像:
"Some Entry"
{
property1 = value1
property2 = value2
}
ConfigSlurper
给我一张这样的地图:
["Some Entry":[property1:value1,property2:value2]]
使用这些值来创建我的对象非常简单,特别是因为我可以将属性/值映射传递给构造函数。