我正在迁移曾经使用 Scala 2 反射的代码。
我正在尝试使用scala-reflection库。
我需要获取案例类中给定名称的字段的值。
例子:
$ scala-cli -j system -S 3.4.2 --dep co.blocke::scala-reflection:2.0.8
scala> import co.blocke.scala_reflection.RType
scala> case class A(a: Int, b: String)
// defined case class A
scala> import co.blocke.scala_reflection.rtypes.ScalaClassRType
scala> val t = RType.of[A].asInstanceOf[ScalaClassRType[A]]
val t: co.blocke.scala_reflection.rtypes.ScalaClassRType[A] = ScalaClassRType(rs$line$2$A,rs$line$2$.A,List(),List(),List(),List(ScalaFieldInfo(0,a,IntRType(),Map(),None,None,false), ScalaFieldInfo(1,b,StringRType(),Map(),None,None,false)),Map(),List(java.lang.Object, scala.Product, java.io.Serializable),false,false,true,false,Map(),List(),List(),false)
scala> t.fields.find(_.name == "a")
val res2: Option[co.blocke.scala_reflection.rtypes.FieldInfo] = Some(ScalaFieldInfo(0,a,IntRType(),Map(),None,None,false))
scala> val c = A(3,"hola")
val c: A = A(3,hola)
在这个例子中,如何a
通过实例反射来获取字段的值c
。
如果更容易的话,我可以考虑使用其他库,如izumi-reflect。
假设您想要通过将事物一个接一个地放入 JDBC 中来序列化它们:
这是一个存根,我将使用它来传递它以调用某些 API。
这将是获取值
A
并以某种方式将其所有数据放入的类型类SerializationTarget
- 不管它看起来像什么。我们将从一些(存根)实例开始,展示如何处理原语:
现在,当我们打电话时
代码会选择正确
given
并使用它,基本上就像一个策略模式,但是该策略是基于类型的DI。最后,我们将使用
Mirror
s 为每个 生成这样的策略case class
:最后我们可以调用它:
每次需要时,它都会创建一个新的实例
SerializeForJDBC[Example]
。这应该不是什么大问题,但如果我们想缓存实例,我们可以使用derives
关键字(因为我们将基于镜像的方法定义为derived
):在实际代码中,您必须用
SerializationTarget
与 JDBC 交互的任何方式进行替换,替换原始的主体given
,并调整如何将每个字段的实例组合成一个整体的实例case class
。内置镜像的替代方案是 Magnolia 库 - 由于它是基于宏的,因此它能够提供比缺失隐式/给定更好的错误消息。如果想要在 Scala 2 和 Scala 3 之间实现交叉编译解决方案,它也是一个不错的选择。