我试图反映一个带有隐式参数的类,如何在运行时获取实际的隐式参数以获取此类的实例?
object Validator extends App {
val between = Between(1, 3)
println(getAnotherInstance(between))
def getAnotherInstance[T: TypeTag](obj: T)(implicit tag: ClassTag[T]) = {
val tpe = typeOf[T]
val lowerTerm = tpe.member(TermName("lower")).asTerm
val upperTerm = tpe.member(TermName("upper")).asTerm
val lower = mirror.reflect(obj).reflectField(lowerTerm).get
val upper = mirror.reflect(obj).reflectField(upperTerm).get
val constructorSymbol = typeOf[T].member(termNames.CONSTRUCTOR).alternatives.head.asMethod
mirror.reflectClass(tpe.typeSymbol.asClass).reflectConstructor(constructorSymbol).apply(lower, upper, Ordering[Int]) // problem is the Ordering[Int]
}
}
case class Between[T](lower: T, upper: T)(implicit order: Ordering[T]) extends ValidateAnnotation {
def validate(name: String, value: T): Option[String] = {
if(order.lteq(value, lower) || order.gteq(value, upper)) Some(s"$name is not between $lower and $upper") else None
}
}
隐式参数Ordering [Int]的实际类型在运行时已确认,有没有办法在运行时获取隐式参数(可能是Ordering [String],Ordering [Date])?这样我就可以将其传递给apply方法,然后获得一个实例。
答案 0 :(得分:0)
尝试
def getAnotherInstance[T: TypeTag : ClassTag : Ordering](obj: Between[T]) = {
val tpe = typeOf[Between[T]]
val lowerTerm = tpe.member(TermName("lower")).asTerm
val upperTerm = tpe.member(TermName("upper")).asTerm
val lower = mirror.reflect(obj).reflectField(lowerTerm).get
val upper = mirror.reflect(obj).reflectField(upperTerm).get
val constructorSymbol = tpe.member(termNames.CONSTRUCTOR).alternatives.head.asMethod
mirror.reflectClass(tpe.typeSymbol.asClass).reflectConstructor(constructorSymbol).apply(lower, upper, Ordering[T])
}
getAnotherInstance(Between(1, 3)).asInstanceOf[Between[Int]].validate("aaa", 10)
// Some(aaa is not between 1 and 3)
getAnotherInstance(Between("a", "c")).asInstanceOf[Between[String]].validate("bbb", "z")
// Some(bbb is not between a and c)
或
def getAnotherInstance[T: TypeTag : ClassTag](obj: T) = {
val tpe = typeOf[T]
val lowerTerm = tpe.member(TermName("lower")).asTerm
val upperTerm = tpe.member(TermName("upper")).asTerm
val orderTerm = tpe.member(TermName("order")).asTerm
val lower = mirror.reflect(obj).reflectField(lowerTerm).get
val upper = mirror.reflect(obj).reflectField(upperTerm).get
val order = mirror.reflect(obj).reflectField(orderTerm).get
val constructorSymbol = tpe.member(termNames.CONSTRUCTOR).alternatives.head.asMethod
mirror.reflectClass(tpe.typeSymbol.asClass).reflectConstructor(constructorSymbol).apply(lower, upper, order)
}
或
def getAnotherInstance[T: TypeTag : ClassTag](obj: T) = {
val tpe = typeOf[T]
val lowerTerm = tpe.member(TermName("lower")).asTerm
val upperTerm = tpe.member(TermName("upper")).asTerm
val orderTypeArg = tpe.member(TermName("order")).typeSignatureIn(tpe).typeArgs.head
val lower = mirror.reflect(obj).reflectField(lowerTerm).get
val upper = mirror.reflect(obj).reflectField(upperTerm).get
val constructorSymbol = tpe.member(termNames.CONSTRUCTOR).alternatives.head.asMethod
import scala.tools.reflect.ToolBox
val order = mirror.mkToolBox().eval(q"Ordering[$orderTypeArg]")
mirror.reflectClass(tpe.typeSymbol.asClass).reflectConstructor(constructorSymbol).apply(lower, upper, order)
}