En primer lugar, hay algunas alternativas seguras que puede hacer si solo quiere acortar su código. El objeto acompañante puede ser tratada como una función de lo que podría utilizar algo como esto:
def build2[A,B,C](m: Map[A,B], f: (B,B) => C)(k1: A, k2: A): Option[C] = for {
v1 <- m.get(k1)
v2 <- m.get(k2)
} yield f(v1, v2)
build2(m, Image)("url", "title")
Esto devolverá una opción que contiene el resultado. Otra posibilidad es utilizar los ApplicativeBuilder
s en Scalaz cuales internamente hacer casi lo mismo pero con una sintaxis más agradable:
import scalaz._, Scalaz._
(m.get("url") |@| m.get("title"))(Image)
Si realmente necesita hacer esto a través de la reflexión a continuación, la manera más fácil sería utilizar Paranamer (ya que el ascensor -Framework lo hace). Paranamer puede restaurar los nombres de los parámetros inspeccionando el bytecode, por lo que hay un golpe de rendimiento y no funcionará en todos los entornos debido a problemas con el cargador de clases (el REPL, por ejemplo).Si se restringe a sí mismo a clases con sólo String
parámetros del constructor, entonces podría hacerlo de esta manera:
val pn = new CachingParanamer(new BytecodeReadingParanamer)
def fill[T](m: Map[String,String])(implicit mf: ClassManifest[T]) = for {
ctor <- mf.erasure.getDeclaredConstructors.filter(m => m.getParameterTypes.forall(classOf[String]==)).headOption
parameters = pn.lookupParameterNames(ctor)
} yield ctor.newInstance(parameters.map(m): _*).asInstanceOf[T]
val img = fill[Image](m)
(Tenga en cuenta que este ejemplo puede escoger un constructor por defecto, ya que no comprueba el recuento de parámetro que usted quiere lo hacen)
Los parámetros de tipo de build2 son directamente proporcionales al número de campos. No tan limpio, creo. –