【问题标题】:How to detect import of a certain library in Scala如何检测Scala中某个库的导入
【发布时间】:2014-12-01 12:09:35
【问题描述】:

我很确定这可以使用反射 API 来完成。

我同时使用 Casbahspray.json 在 Scala 项目中创建 JSON 文档 - 一个用于 MongoDB,另一个用于 REST API。

这有时会让人感到困惑。我想在某个源文件中检测并禁止 import 的“错误”库,以确保将来的编辑永远不会在同一代码中混合这两种方法。

可能没有编译时机制可以做到这一点(宏除外,不想走这么深)。

运行时方法(例如,放置在 object 主体中,以便它在前面运行)就可以了。 IE。在 Scala 中,如何告诉 spray.json 命名空间已导入此范围?


较早的问题:Prevent imports of unauthorized classes in Scala 很接近,但更多的是关于沙盒(不受信任的代码)

【问题讨论】:

  • 我不认为反思是正确的方法。类型系统不应该明确要求吗?你可以为你的“restification”设置一个单一的访问点,它需要[T: JsonFormat],这将需要喷雾,同样对于你的 mongo 东西,你有一个需要 Casbah 类型的“dao”,那么导入什么并不重要,将使用正确的类型。如果您真的坚持这样做,我建议您在构建过程中使用 Checkstyle 之类的东西;这可能比反射更简单、更容易混淆。
  • 这是个好主意,@lmm。让我换个说法:你的意思是通过函数或类原型给它一个类型约束/隐式来强加“这部分使用 Casbah”,根本不需要导入。那会奏效。但是,它仍然不能防止人们通过简单地键入 JsString 并让 IDE 自动为他们添加导入来意外进入“错误的一面”。这是“问题”的一部分——IDE 可以很容易地引入不需要的依赖项,在这种情况下,它们会在很久以后被发现为奇怪的序列化异常。我想避免这种情况。
  • 我不明白你是如何得到“奇怪的序列化异常”的。使用 spray-json 序列化某些东西的唯一方法是它是否有 JsonFormat;如果没有(如 Casbah 类型的情况),您应该会收到编译错误。我不知道 Casbah,但要么它已经以相同的方式工作,要么你可以这样做(通过只有一个地方序列化到 Casbah,创建你自己的隐式(CasbahFormat?),并且只有隐含的实例Casbah 类型,而不是 spray-json 类型)。
  • 我所经历的恰恰相反:Casbah 在 BigInteger 上窒息,这是由于意外向它提供了一个 JsNumber。这让我思考如何防止其他人发生这种情况,稍后维护代码。只是问...我可能会以错误的方式剥离它。

标签: scala reflection


【解决方案1】:

在澄清您的 cmets 之后,我要做的是根据哪些类型是“安全的”来结束 Casbah 序列化。有一个“网关”方法来执行您的 Casbah 序列化,以及一个标记接口,说明哪些类型可以“安全”发送到 Casbah

trait CasbahSafe[T]

object CasbahSafe {
  implicit val intsAreSafe = new CasbahSafe[Int]{}
  implicit val stringsAreSafe = new CasbahSafe[String]{}
  ...
}

def saveToMongo[T: CasbahSafe](t: T) = ...

那么saveToMongo只能用合适的类型调用;如果您尝试使用JsNumber 调用它,您将收到编译错误。对于复合类型,您可以使用Shapeless automatic typeclass derivation 为所有字段均为CasbahSafe 的任何案例类派生CasbahSafe

整体效果与spray-json对JsonFormat的作用非常相似。 “在相反的方向上犯同样的错误”应该已经不可能了,因为 JsonFormat 的存在是由编译器强制执行的。

【讨论】:

    猜你喜欢
    • 2017-08-28
    • 2021-02-10
    • 2015-05-23
    • 2022-12-01
    • 1970-01-01
    • 2012-12-02
    • 2020-01-09
    • 1970-01-01
    • 2020-02-22
    相关资源
    最近更新 更多