Access values of static closure in Groovy
I'd like to store some properties in a static closure and later access them during a method call:
class Person {
static someMap = { key1: "value1", key2: "value2" }
}
So how can I write a m开发者_运维技巧ethod within Person, which retrieves this stored data?
For the simple case, you're better off using a map.
If you really do want to evaluate it as a closure (possibly to create your own DSL), you'll need to change your syntax slightly as John points out. Here's one way to do it using a Builder class to evaluate the "something" closure within whatever is passed to the builder.
It uses groovy metaprogramming to intercept calls with method/property missing and to save them off:
class SomethingBuilder {
Map valueMap = [:]
SomethingBuilder(object) {
def callable = object.something
callable.delegate = this
callable.resolveStrategy = Closure.DELEGATE_FIRST
callable()
}
def propertyMissing(String name) {
return valueMap[name]
}
def propertyMissing(String name, value) {
valueMap[name] = value
}
def methodMissing(String name, args) {
if (args.size() == 1) {
valueMap[name] = args[0]
} else {
valueMap[name] = args
}
}
}
class Person {
static something = {
key1 "value1" // calls methodMissing("key1", ["value1"])
key2("value2") // calls methodMissing("key2", ["value2"])
key3 = "value3" // calls propertyMissing("key3", "value3")
key4 "foo", "bar", "baz" // calls methodMissing("key4", ["foo","bar","baz"])
}
}
def builder = new SomethingBuilder(new Person())
assert "value1" == builder."key1" // calls propertyMissing("key1")
assert "value2" == builder."key2" // calls propertyMissing("key2")
assert "value3" == builder."key3" // calls propertyMissing("key3")
assert ["foo", "bar", "baz"] == builder."key4" // calls propertyMissing("key4")
If they need to be initialized by a closure, instead of a map, then somebody's got to run the closure in order to pick up and record the values as they're set.
Your syntax there isn't valid. Remember closures are just anonymous methods. Your syntax looks like you're trying to define a map, but closures would need to call methods, set variables or return maps. e.g.
static someClosure = { key1 = "value1"; key2 = "value2" } // set variables
static someClosure = { key1 "value1"; key2 = "value2" } // call methods
static someClosure = { [key1: "value1", key2: "value2"] } // return a map
Then of course whoever's running the closure needs to have the right metaprogramming to record the results.
It sounds like what you really want is just to define a map.
static someMap = [key1: "value1", key2: "value2"]
This is what I came up with to extract static closure properties:
class ClosureProps {
Map props = [:]
ClosureProps(Closure c) {
c.delegate = this
c.each{"$it"()}
}
def methodMissing(String name, args) {
props[name] = args.collect{it}
}
def propertyMissing(String name) {
name
}
}
// Example
class Team {
static schema = {
table team
id teamID
roster column:playerID, cascade:[update,delete]
}
}
def c = new ClosureProps(Team.schema)
println c.props.table
精彩评论