mardi 24 février 2015

Reflecting Enumerations in Scala

How can I best reflect Enermations in Scala such that I can create Value objects from a string later?


For example:



object Num extends Enumeration {
val Aaa,Bbb,Ccc = Value
}
case class Boom( name:String, num:Num.Value )

def staticScan(
ctype:Type
) = {
ctype.typeSymbol match {
case s if(s.fullName == "scala.Enumeration.Value") =>
val owner = s.owner.asClass // Finds "scala.Enumeration"
// Now what?

// This is kinda awful, but it does work...
val erasedEnumClass = Class.forName(ctype.asInstanceOf[TypeRef].toString.replace(".Value","$"))
val enum = erasedEnumClass.getField(scala.reflect.NameTransformer.MODULE_INSTANCE_NAME).get(null).asInstanceOf[Enumeration]

enum
}
}

val enumThing = staticScan(currentMirror.classSymbol(Boom("Fred",Num.Aaa).getClass).typeSignature)
val newEnum = enumThing.withName("Bbb") // Creates Num.Value of Bbb


Is there a cleaner way to do this presuming static reflection? I may not always have an object available?


I've tried something like this but didn't work:



val ctor = owner.primaryConstructor
val maker = currentMirror.reflectClass(owner).reflectConstructor(ctor.asMethod)
...
maker.apply().asInstanceOf[Enumeration].withName("Bbb")





Aucun commentaire:

Enregistrer un commentaire