Scala:如何使用反射将枚举转换为地图?

时间:2014-02-04 10:03:50

标签: scala reflection enumeration

是否可以编写类似

的方法
def enumToMap[E <: Enumeration]: Map[String, Int]

对于给定的枚举,f.e。

object PROTOCOL_TYPE extends Enumeration{
  type PROTOCOL_TYPE = Value
  val HELLO = Value(0)
  val ERROR = Value(1)
  ...
} 

将生成地图

Map("HELLO" -> 0, "ERROR" -> 1, ...)

我发现了一个类似的问题: Using Scala 2.10 reflection how can I list the values of Enumeration?,但我无法掌握如何获得整数id。

2 个答案:

答案 0 :(得分:1)

试试这个,

def enumToMap[E <: Enumeration](e:E) = e.values.map { v => (v.toString,v.id) }.toMap

请注意,此方法不使用反射。

然后

scala> enumToMap(PROTOCOL_TYPE)
res9: scala.collection.immutable.Map[String,Int] = Map(ERROR -> 1, HELLO -> 0)

<强>更新

另一种致电enumToMap的方式,

implicit def test[E <: Enumeration] (e:E) = new { def !() = enumToMap(e) }

因此,

scala>  PROTOCOL_TYPE !
res4: scala.collection.immutable.Map[String,Int] = Map(ERROR -> 1, HELLO -> 0)

此语法!可根据需要更改为与上下文相关的运算符/符号。

答案 1 :(得分:0)

我找到了解决方案。主要思想是按值类型查找伴随对象。这是我的代码:

def enumObjectForType[T <: Enumeration](implicit tt: TypeTag[T]) = {
  val universeMirror = runtimeMirror(getClass.getClassLoader)
  val objModule = typeOf[T].asInstanceOf[TypeRef].pre
                           .typeSymbol
                           .companionSymbol
                           .asModule
  val companionMirror = universeMirror.reflectModule(objModule)
  companionMirror.instance
}

def enumToMap[T <: Enumeration#Value](implicit tt: TypeTag[T]) = {
  val ett = tt.asInstanceOf[TypeTag[Enumeration]]
  val instance = enumObjectForType(ett).asInstanceOf[Enumeration]
  instance.values map { v => (v.toString, v.id)} toMap
}

用法:

object PROTOCOL_TYPE extends Enumeration{
  type PROTOCOL_TYPE = Value
  val HELLO = Value(0)
  val ERROR = Value(1)
}

import PROTOCOL_TYPE._
println(enumToMap[PROTOCOL_TYPE]) // output is Map(HELLO -> 0, ERROR -> 1)