With hints from dveim in this answer, I'm adding a second solution that works both in Scala 2.10 and 2.11 and uses Scala Toolbox. The generated cases classes unfortunately are in the default package.
Generate Case Class
/**
* Generate a case class and persist to file
* Can't add package to the external class
* @param file External file to write to
* @param className Class name
* @param header case class parameters
*/
def writeCaseClass(file: File, className: String, header: String): Unit = {
val writer: PrintWriter = new PrintWriter(file)
writer.println("case class " + className + "(")
writer.println(header)
writer.println(") {}")
writer.println("
scala.reflect.classTag[" + className + "].runtimeClass")
writer.flush()
writer.close()
}
Compile external classes using Toolbox
/**
* Helper method to search code files in directory
* @param dir Directory to search in
* @return
*/
def recursiveListFiles(dir: File): Array[File] = {
val these = dir.listFiles
these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
}
/**
* Compile scala files and keep them loaded in memory
* @param classDir Directory storing the generated scala files
* @throws IOException if there is problem reading the source files
* @return Map containing Class name -> Compiled Class Reference
*/
@throws[IOException]
def compileFiles(classDir: String): Map[String, Class[_]] = {
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
val files = recursiveListFiles(new File(classDir))
.filter(_.getName.endsWith("scala"))
println("Loaded files:
" + files.mkString("[", ",
", "]"))
files.map(f => {
val src = Source.fromFile(f).mkString
val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]]
getClassName(f.getName) -> clazz
}).toMap
}
Instantiate and Use compiled classes
The compiled class can be obtained from the map and used where necessary e.g.
//Test Address class
def testAddress(map: Map[String, Class[_]]) = {
val addressClass = map("AddressData")
val ctor = addressClass.getDeclaredConstructors()(0)
val instance = ctor.newInstance("123 abc str", "apt 1", "Hello world", "HW", "12345")
//println("Instantiated class: " + instance.getClass.getName)
println(instance.toString)
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…