2011-03-30 18 views
8

Me pregunto cuál es la mejor manera de recuperar propiedades anidadas en Groovy, tomando un Objeto dado y una "propiedad" arbitraria. Me gustaría algo como esto:cómo recuperar propiedades anidadas en groovy

someGroovyObject.getProperty("property1.property2") 

que he tenido un tiempo difícil encontrar un ejemplo de otros que quieran hacer esto, así que tal vez no voy a la comprensión de algunos conceptos básicos maravilloso. Parece que debe haber alguna manera elegante de hacer esto.

Como referencia, hay una característica en Wicket eso es exactamente lo que estoy buscando, llamado el PropertyResolver: http://wicket.apache.org/apidocs/1.4/org/apache/wicket/util/lang/PropertyResolver.html

Alguna pista serán bienvenidos!

Respuesta

22

No sé si Groovy tiene una forma integrada de hacerlo, pero aquí hay 2 soluciones. Ejecute este código en el Groovy Console para probarlo.

def getProperty(object, String property) { 

    property.tokenize('.').inject object, {obj, prop ->  
    obj[prop] 
    } 
} 

// Define some classes to use in the test 
class Name { 
    String first 
    String second 
} 

class Person { 
    Name name 
} 

// Create an object to use in the test 
Person person = new Person(name: new Name(first: 'Joe', second: 'Bloggs')) 

// Run the test 
assert 'Joe' == getProperty(person, 'name.first') 

///////////////////////////////////////// 
// Alternative Implementation 
///////////////////////////////////////// 
def evalProperty(object, String property) { 
    Eval.x(object, 'x.' + property) 
} 

// Test the alternative implementation 
assert 'Bloggs' == evalProperty(person, 'name.second') 
+0

Esto es más o menos lo que estoy haciendo ahora, pero tu camino es más limpio! –

+0

lo siento, Don, debería haber aceptado su respuesta hace mucho tiempo (cuando yo no sabía lo que estaba haciendo en este sitio). gracias ... –

+0

Nota: Probé estos en un tipo, y Eval fue mucho más lento que la versión tokenizada en mi sistema. –

2

Groovy Beans le permiten acceder a los campos directamente. No es necesario definir métodos getter/setter. Se generan para ti. Cada vez que accede a una propiedad de frijol, el método getter/setter se llama internamente. Puede omitir este comportamiento utilizando el operador. @. Véase el siguiente ejemplo:

class Person { 
    String name 
    Address address 
    List<Account> accounts = [] 
} 

class Address { 
    String street 
    Integer zip 
} 

class Account { 
    String bankName 
    Long balance 
} 

def person = new Person(name: 'Richardson Heights', address: new Address(street: 'Baker Street', zip: 22222)) 
person.accounts << new Account(bankName: 'BOA', balance: 450) 
person.accounts << new Account(bankName: 'CitiBank', balance: 300) 

Si no se trata de colecciones se puede simplemente llamar el campo al que desea acceder.

assert 'Richardson Heights' == person.name 
assert 'Baker Street' == person.address.street 
assert 22222 == person.address.zip 

Si desea acceder a un campo dentro de una colección que tiene que seleccionar el elemento:

assert 'BOA' == person.accounts[0].bankName 
assert 300 == person.accounts[1].balance​​​​​​​​​ 
+1

Este es un buen consejo, pero quiero poder tomar una cadena. ¿Hay alguna manera de forzar _persona ". Address.street" _ a devolver el valor de _person.address.street_? –

+0

Puede usar [invocación de método dinámico de Groovy] (http://groovy.codehaus.org/Dynamic+Groovy). Sin embargo, requiere que declare el nombre del método: person. "GetAddress"(). "GetStreet"(). –

+0

gracias por la información y el enlace ... leeré sobre esto y veré si puede ayudar aquí. –

1

También puede usar propertyMissing. Esto es lo que podrías llamar el método incorporado de Groovy.

nuevas de esto en su clase:

def propertyMissing(String name) { 
    if (name.contains(".")) { 
     def (String propertyname, String subproperty) = name.tokenize(".") 
     if (this.hasProperty(propertyname) && this."$propertyname".hasProperty(subproperty)) { 
      return this."$propertyname"."$subproperty" 
     } 
    } 
} 

A continuación, se refieren a sus propiedades como desee:

def properties = "property1.property2" 
assert someGroovyObject."$properties" == someValue 

Este es automáticamente recursiva, y que no tiene que llamar explícitamente a un método. Esto es solo un getter, pero puede definir una segunda versión con parámetros para hacer un setter también.

La desventaja es que, por lo que puedo ver, solo puede definir una versión de propertyMissing, por lo que debe decidir si la ruta de acceso dinámica es para lo que desea usarla.

Cuestiones relacionadas