用Scala进行依赖注入 [英] Dependency injection with Scala

查看:140
本文介绍了用Scala进行依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Scala中寻找一种进行依赖注入的方法,例如Spring或C#中的Unity,但我发现没有什么真正有趣的。

I was searching a way of doing dependency injection in Scala kind of like Spring or Unity in C# and I found nothing really interesting.


  • MacWire:我不明白这样做的好处,因为我们必须通过wire [CASS]进行授课。那么,当您致电wire时给出实施方案有什么意义呢?我可以做新的CASS了。

  • 带有自我类型的蛋糕模式:似乎不回答我要搜索的内容。

因此,我决定进行实施并询问您的想法,因为令我惊讶的是,以前没有做过这样的事情。也许我的实现在现实生活中也有很多问题。

So I decided to make my implementation and ask you what do you think because it's surprising me that nothing like this has been done before. Maybe my implementation have lot's of issues in real life also.

所以这是一个例子:

trait Messenger {
  def send
}

class SkypeMessenger extends Messenger {
  def send = println("Skype")
}

class ViberMessenger extends Messenger {
  def send = println("Viber")
}

我想在这里将应用程序中的所有位置注入仅在一个位置配置的实现:

I want here to inject everywhere in my app the implementation configured in only one place:

object App {
  val messenger = Inject[Messenger]

  def main(args: Array[String]) {
    messenger.send
  }
}

注意下面定义的Inject [Messenger]和想要的配置(产品或开发人员):

Note the Inject[Messenger] that I define like below with the config I want (prod or dev):

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")
}

最后是这里的注入器,其中包含所有应用和注册的方法:

And finally here is the Injector which contains all methods apply and 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)和实现实例之间的映射。

  • 我们为每个包含寄存器的配置(dev,prod ...)定义一个特征。

  • 我们使用所需的Config创建Injector的实例

  • 用法是调用给出接口类型(最后也是id)的apply方法,它将返回实现的实例。

  • I have a class Injector which is a Map between interfaces/traits (eventually also an id) and an instance of the implementation.
  • We define a trait for each config (dev, prod...) which contains the registers. It also have a self reference to Injector.
  • And we create an instance of the Injector with the Config we want
  • The usage is to call the apply method giving the Interface type (eventually also an id) and it will return the implementation's instance.

您怎么看?

推荐答案

您的代码看起来很像Lift Web框架中的依赖项注入。您可以查阅Lift源代码以了解其实现方式或仅使用框架。您无需运行Lift应用即可使用其库。这是一个小介绍 doc 。基本上,您应该在Lift中查看以下代码:

You code looks a lot like dependency injection in Lift web framework. You can consult Lift source code to see how it's implemented or just use the framework. You don't have to run a Lift app to use its libraries. Here is a small intro doc. Basically you should be looking at this code in Lift:

package net.liftweb.http

/**
 * A base trait for a Factory.  A Factory is both an Injector and
 * a collection of FactorMaker instances.  The FactoryMaker instances auto-register
 * with the Injector.  This provides both concrete Maker/Vender functionality as
 * well as Injector functionality.
 */
trait Factory extends SimpleInjector

您还可以检查以下相关问题: Scala-编写单元测试用于通过DB连接扩展特征/类的对象/单次操作,其中我演示了如何使用Lift注入器。

You can also check this related question: Scala - write unit tests for objects/singletons that extends a trait/class with DB connection where I show how Lift injector is used.

这篇关于用Scala进行依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆