2

我通过扩展 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”节点。我已经尝试了许多变体,包括将文本块直接传递到构建器而不将其包装在闭包中。它们都产生相同的结果。

有什么方法可以获取一段任意文本并将其传递给我的构建器,以便它能够正确解析和构建它?

4

3 回答 3

1

您的问题是 String 不是 Groovy 代码。处理这个问题的方法ConfigSlurper是将文本编译成Scriptusing的实例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)
}

它相当于你上面的代码。

于 2009-12-28T22:08:18.427 回答
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
}
于 2009-11-24T07:51:54.290 回答
0

最初,我希望能够指定

"Some Entry" (property1:value1, property2: value2)

在外部文件中。我特别试图避免使用 XML 和类似 XML 的语法,以使普通用户更容易创建和修改这些文件。我当前的解决方案使用ConfigSlurper,文件现在看起来像:

"Some Entry"
{ 
   property1 = value1 
   property2 = value2 
}

ConfigSlurper给我一张这样的地图:

["Some Entry":[property1:value1,property2:value2]]

使用这些值来创建我的对象非常简单,特别是因为我可以将属性/值映射传递给构造函数。

于 2009-11-25T17:44:00.763 回答