动态实例化中scala构造函数的完美处理

动态实例化中scala构造函数的完美处理,scala,Scala,我已经把这个工作代码放在一起,它动态地从给定的名称:String(如下)实例化一个类。这适用于easy case类和具有一个构造函数的case类 我不知道如何处理存在多个构造函数的一般情况。我假设它们只能通过它们的签名来区分,但是发现伴随对象、类和case类之间的概念性交互有点令人费解。需要说明的所有“构建”场景的完整描述是什么,或者,您将如何将其演变为完全通用的 这段代码显示了它的不灵活性,令人尴尬的是,它在遍历同伴对象时失败了 希望这段代码能提供方便的测试和修补流程,如果有人愿意加入这个思想

我已经把这个工作代码放在一起,它动态地从给定的
名称:String
(如下)实例化一个类。这适用于easy case类和具有一个构造函数的case类

我不知道如何处理存在多个构造函数的一般情况。我假设它们只能通过它们的签名来区分,但是发现伴随对象、类和case类之间的概念性交互有点令人费解。需要说明的所有“构建”场景的完整描述是什么,或者,您将如何将其演变为完全通用的

这段代码显示了它的不灵活性,令人尴尬的是,它在遍历同伴对象时失败了

希望这段代码能提供方便的测试和修补流程,如果有人愿意加入这个思想训练的话

import scala.reflect.runtime.universe

case class CaseClass(foo: Int) {
  println(s"${getClass.getSimpleName} Instantiated with $foo")
}

class BaseClass(foo: Int) {
  println(s"${getClass.getSimpleName} Instantiated with $foo")
}

object BaseClass { 
  def apply(foo:Int) = {
    println(s"going through companion object ${getClass.getSimpleName}")
    new BaseClass(foo+10) }
  }

class GenericClass[T](foo: T) {
  println(s"${getClass.getSimpleName} Instantiated with $foo")
}

object Inst {

  private def log(s: String) = println(Console.YELLOW + Console.BOLD + s + Console.RESET)

  private def selectConstructor(symbol: universe.Symbol) = {
    val constructors = symbol.typeSignature.members.filter(_.isConstructor).toList
    if (constructors.length > 1) log(
           s"""Warning: $symbol has several constructors, arbitrarily picking the first one: 
              |         ${constructors.mkString("\n         ")}""".stripMargin)
    constructors.head.asMethod
  }

  def apply(className: String, arg: Any) = {
    val runtimeMirror: universe.Mirror = universe.runtimeMirror(getClass.getClassLoader)

    val classSymbol: universe.ClassSymbol = runtimeMirror.classSymbol(Class.forName(className))

    val classMirror: universe.ClassMirror = runtimeMirror.reflectClass(classSymbol)

    if (classSymbol.companion.toString() == "<none>") // TODO: use nicer method "hiding" in the api?
    {
      log(s"Info: $className has no companion object")
      val constructorMirror = classMirror.reflectConstructor(selectConstructor(classSymbol)) // we can reuse it
      constructorMirror(arg)
    }
    else
    {
      val companionSymbol = classSymbol.companion
      log(s"Info: $className has companion object $companionSymbol")
      val constructorMirror = classMirror.reflectConstructor(selectConstructor(classSymbol)) // we can reuse it
      constructorMirror(arg)
    }   
  }
}

object Test extends App {
  val c1 = Inst("BaseClass", 3)
  val c2 = Inst("BaseClass", 4)
  val cc = Inst("CaseClass", 5)
  val gc1 = Inst("GenericClass", "I am generic")
  val gc2 = Inst("GenericClass", gc1)
  println(s"""\nthese objects have been instantiated:\n${List(c1,c2,cc,gc1,gc2).mkString("\n")}""")
}
lazy val reflection = (project in file("."))
  .settings(
    scalaVersion := "2.11.7",
    libraryDependencies ++= Seq(
      "org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided",
      "org.scala-lang" % "scala-library" % scalaVersion.value % "provided"
    )
  )