我正在寻找一种在 Scala 中进行依赖注入的方法,类似于 C# 中的 Spring 或 Unity,但我没有发现任何真正有趣的东西。
- MacWire:我不明白这样做有什么好处,因为我们必须在wire[CASS]中上课。那么如果你在调用wire时给出实现又有什么意义呢?我可以做新的 CASS,它会是一样的。
- 具有自我类型的蛋糕图案:似乎没有回答我正在寻找的内容。
因此,我决定实施并询问您的想法,因为令我惊讶的是,以前从未做过这样的事情。也许我的实现在现实生活中也存在很多问题。
这是一个例子:
trait Messenger {
def send
}
class SkypeMessenger extends Messenger {
def send = println("Skype")
}
class ViberMessenger extends Messenger {
def send = println("Viber")
}
我想在我的应用程序中的所有位置注入仅在一个地方配置的实现:
object App {
val messenger = Inject[Messenger]
def main(args: Array[String]) {
messenger.send
}
}
请注意我使用我想要的配置(产品或开发)定义的 Inject[Messenger],如下所示:
object Inject extends Injector with DevConfig
trait ProdConfig {
this: Injector =>
register[Messager](new SkypeMessager)
register[Messager](new ViberMessager, "viber")
}
trait DevConfig {
this: Injector =>
register[Messager](new ViberMessager)
register[Messager](new ViberMessager, "viber")
}
最后是注入器,其中包含所有 apply 和 register 方法:
class Injector {
var map = Map[String, Any]()
def apply[T: ClassTag] =
map(classTag[T].toString).asInstanceOf[T]
def apply[T: ClassTag](id: String) =
map(classTag[T].toString + id).asInstanceOf[T]
def register[T: ClassTag](instance: T, id: String = "") = {
map += (classTag[T].toString + id -> instance)
instance
}
}
总结一下:
- 我有一个类 Injector,它是接口/特征(最终也是一个 id)和实现实例之间的映射。
- 我们为每个包含寄存器的配置(开发、产品...)定义一个特征。它还有一个对 Injector 的自引用。
- 然后我们使用我们想要的配置创建一个 Injector 实例
- 用法是调用提供接口类型(最终也是一个 id)的 apply 方法,它将返回实现的实例。
你怎么认为?