如何解决通过反射获取案例类字段的麻烦
我有一个scala代码:特质模型及其实现案例类带有自定义注释的类别,我希望稍后阅读
import scala.annotation.StaticAnnotation
class ExtraFields() extends StaticAnnotation
trait Model {}
case class MyCategory( id: Option[Int],name: String,level: Option[Int],@ExtraFields
parent: Option[MyCategory] = None
) extends Model {
}
并且我有特征DBModel及其实现MyCategoryModel。我将MyCategory作为类型参数传递给DBModel
trait DBModel[T <: Model] {
lazy val fields = getClassFields[T]
lazy val fields2 = getClassFields2[T]
}
object MyCategoryModel extends DBModel[MyCategory] {
def getFields = fields
def getFields2 = fields2
}
我希望特征DBModel读取作为T参数传递的案例类的字段,所以我调用了两个函数
def getClassFields[T] = {
symbolOf[T].asClass.primaryConstructor
.typeSignature.paramLists.head.map {v =>
v.name.toString -> v.annotations
}
}
def getClassFields2[T: TypeTag]: Iterable[(String,List[universe.Annotation])] =
typeOf[T].members.collect {
case m: MethodSymbol if m.isCaseAccessor =>
m.name.toString -> m.annotations
}
但它们都不起作用
val res = MyCategoryModel.getFields // runtime exception: free type T is not a class
val res2 = MyCategoryModel.getFields2 // compile error: No TypeTag available for T
如果我直接打电话给他们
getClassFields[MyCategory]
getClassFields2[MyCategory]
对于第一个函数,我得到了相同的错误,对于第二个函数,我得到了结果,但Universe.annotations无法看到我的ExtraFields批注,为每个字段返回空列表
请问您能解释一下这种黑魔法,以及如何在我的情况下进行征服 谢谢
UPD游乐场https://scastie.scala-lang.org/DTTTyA0CSTSZ0Vj7KFW6Hw
解决方法
您缺少WeakTypeTag
的类型类getClassFields
。
此外,您没有在特征DBModel[T <: Model]
中传递类型类。
一种解决方案是将它们定义为类型T
的上下文边界。但是要使其正常工作,需要通过构造函数传递这些类型类。而且由于特征没有构造函数,解决方案是使用abstract class
。
因此,以下内容可解决编译问题
abstract class DBModel[T <: Model : WeakTypeTag : TypeTag] {
lazy val fields = getClassFields[T]
lazy val fields2 = getClassFields2[T]
}
def getClassFields[T: WeakTypeTag] = ???
def getClassFields2[T: TypeTag] = ???
由于指定了注释,方法getClassFields2
找不到注释。如果定义如下,则这两种方法均有效。有关更多信息,请阅读meta docs
import scala.annotation.meta.{getter,param}
case class MyCategory(
id: Option[Int],name: String,level: Option[Int],@(ExtraFields @param @getter) parent: Option[MyCategory] = None
) extends Model
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。