【问题标题】:Get All the instance subclass of trait using Google Guice使用 Google Guice 获取 trait 的所有实例子类
【发布时间】:2017-11-28 18:02:55
【问题描述】:

我正在尝试获取特征(接口)的所有实例子类。此 trait 有多种实现,由第三方用户提供。

这是否可能在没有显式绑定的情况下获取所有实例子类,因为我没有控制权,由第三方用户提供的实现。 ?

我已经看到了相同的question,您需要在其中显式绑定。

代码示例:

import javax.inject.Inject

import com.google.inject._

import scala.collection.JavaConversions._


object DemoApp extends App {
  val injector = Guice.createInjector(new AllImplModule)
  injector.getInstance(classOf[Action]).perform()


}

class Action @Inject()(impls: List[B]) {

  def perform() = {
    impls.foreach(b => println(b.name))
  }

}

class AllImplModule extends AbstractModule {
  override def configure() = {
    bind(classOf[Action]).asEagerSingleton()
  }

  @Provides
  @Singleton
  def getAllImpls(injector: Injector): List[B] = {
    injector.getAllBindings().keySet().collect {
      case key: Key[_] if (classOf[B].isAssignableFrom(key.getTypeLiteral().getRawType())) =>
        injector.getInstance(key).asInstanceOf[B]
    }.toList

  }
}

trait B {
  def name: String
}

class C1 extends B {
  override def name: String = "C1"

}


class C2 extends B {
  override def name: String = "C2"
}

这不起作用。任何帮助,将不胜感激!

【问题讨论】:

    标签: scala dependency-injection guice


    【解决方案1】:

    您可以使用 guice-multibindings 扩展来注入 trait 的多个实现。

    "com.google.inject.extensions" % "guice-multibindings" % "4.1.0" 添加到您的 build.sbt 文件中

    在 Play 模块中定义您的绑定,如下所示:

     val multipleBinder = Multibinder.newSetBinder(binder(),classOf[BaseTrait])
     multipleBinder.addBinding().to(classOf[Implementation1])
     multipleBinder.addBinding().to(classOf[Implementation2])
    

    当你想注入你的多个绑定时,在组件中以这种方式声明依赖:

    baseTraits: java.util.Set[BaseTrait]
    

    那么它应该可以工作了。

    【讨论】:

      【解决方案2】:

      您的示例代码看起来不错。这是一个 Scala 工作表,可以动态查找某个 abstract class/trait 的所有绑定实现。

      import com.google.inject.{AbstractModule, Guice}
      import scala.collection.JavaConverters._
      
      trait Foo {
          def name: String
      }
      class Foo1 extends Foo {
          override def name = "Foo1"
      }
      class Foo2 extends Foo {
          override def name = "Foo2"
      }
      
      val testModule = new AbstractModule {
          override def configure(): Unit = {
              bind(classOf[Foo1]).toInstance(new Foo1)
              bind(classOf[Foo2]).toInstance(new Foo2)
              bind(classOf[Int]).toInstance(42)
          }
      }
      
      val injector = Guice.createInjector(testModule)
      
      private def bindingsFor[T](c: Class[T]): Iterable[T] = injector.getAllBindings.asScala.keys
          .filter { key ⇒ c.isAssignableFrom(key.getTypeLiteral.getRawType) }
          .map { key ⇒ injector.getInstance(key).asInstanceOf[T] }
      
      bindingsFor(classOf[Foo]).map(_.name).mkString(", ")
      

      返回:

      output: String = Foo1, Foo2
      

      【讨论】:

        猜你喜欢
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-11
        • 2015-05-29
        • 2013-08-21
        相关资源
        最近更新 更多