Создание экземпляра класса из карты значений параметров конструктора - PullRequest
3 голосов
/ 23 декабря 2011

Скажите, у меня есть следующий класс:

case class Mock(id: Int, pty1: String, pty2: String)

Как я могу создать его динамически на следующей карте?

val params = Map("id" → 234, "pty1" → "asdf", "pty2" → "asdf")

Ответы [ 2 ]

6 голосов
/ 23 декабря 2011

LOL) Обнаружил, что у меня уже есть решение, реализованное в моей библиотеке.Требуется Scala 2.10.

  def instantiate[T <: AnyRef : Manifest](params: Map[String, Any]): T = {
    instantiate(Mirror.classToType(manifest[T].erasure), params).asInstanceOf[T]
  }
  def instantiate(tpe: Mirror.Type, params: Map[String, Any]) = {
    val p = constructorParams(tpe, params)
    require(
      params.size == p.size &&
      p.forall(p => params.contains(p.nameString)),
      "Params map `" + params + "` doesn't match `" + p + "`"
    )
    Option(Mirror.typeToJavaClass(tpe).getConstructor(p.map(p => Mirror.typeToJavaClass(p.tpe)): _*))
      .getOrElse(throw new RuntimeException("No appropriate constructor of `" + tpe + "` found"))
      .newInstance(p.map(p => params(p.nameString).asInstanceOf[Object]): _*)
  }
  private def constructorParams(tpe: Mirror.Type, params: Map[String, Any]) = {
    tpe.members.find(_.isConstructor).get.paramss(0)
  }
1 голос
/ 23 декабря 2011

Я не думаю, что вы можете быть детерминистическим способом, поскольку имена параметров не являются частью байтового кода, и поэтому во время выполнения нет способа узнать, какой аргумент String стоит первым, а какой - вторым.

...