Использовать мультисвязи Guice с вспомогательным вводом для заданных членов

1

У меня есть класс PluginManager который принимает Set<Plugin> используя функцию Guis multi-bindings. Тем не менее, PluginManager имеет некоторую информацию о времени выполнения, которая должна быть передана конструктору Plugin.

Это, по-видимому, идеальный вариант использования для инъекций с помощью Guice, т.е. у моего PluginManager бы установлен Set<PluginFactory>, где информация о времени выполнения предоставляется на каждом заводе, в результате чего требуются экземпляры Plugin.

Однако я не знаю, какой синтаксис использовать в Module. У addBinding нет никакого средства для подключения результата FactoryModuleBuilder.

Я могу создать собственные пользовательские реализации Factory и multibind, которые, очевидно, но есть ли способ комбинировать мультиинжинер с вспомогательной инъекцией?

Теги:
guice

1 ответ

2
Лучший ответ

Я думаю, это дает вам пример, чтобы сделать именно то, что вы хотите. Обратите внимание, что scala multibinder имеет ожидающий запрос на растяжение, который позволяет вам создавать набор связующего в нескольких местах.

object Test {
  trait Plugin {
    def name(): String
  }

  object Plugin {
    trait Factory[+T <: Plugin] {
      def newPlugin(name: String): T
    }
  }

  case class MyPlugin @Inject() (@Assisted name: String) extends Plugin
  case class OtherPlugin @Inject() (@Assisted name: String) extends Plugin

  class PluginManager @Inject() (pluginFactories: Set[Plugin.Factory[Plugin]]) {
    for (factory <- pluginFactories) {
      println(factory.newPlugin("assisted injection"))
    }
  }

  def main(args: Array[String]): Unit = {
    val injector = Guice.createInjector(new ScalaModule {
      override def configure(): Unit = {
        val plugins = ScalaMultibinder.newSetBinder[Plugin.Factory[Plugin]](binder)
        plugins.addBinding().to[Plugin.Factory[MyPlugin]]
        plugins.addBinding().to[Plugin.Factory[OtherPlugin]]

        bindFactory[Plugin, MyPlugin, Plugin.Factory[MyPlugin]]()
        bindFactory[Plugin, OtherPlugin, Plugin.Factory[OtherPlugin]]()

        bind[PluginManager].asEagerSingleton()
      }

      def bindFactory[I: Manifest, C <: I : Manifest, F: Manifest](): Unit = {
        import net.codingwell.scalaguice._
        install(new FactoryModuleBuilder()
          .implement(typeLiteral[I], typeLiteral[C])
          .build(typeLiteral[F]))
      }
    })
  }
}

Вы можете сделать кучу вещей в зависимости от стиля, который вы хотите. Например, вы можете создать общий метод addPlugin (когда будет выпущена более новая версия scala-guice) следующим образом:

val injector = Guice.createInjector(new ScalaModule {
  override def configure(): Unit = {
    bindPlugin[MyPlugin]()
    bindPlugin[OtherPlugin]()

    bind[PluginManager].asEagerSingleton()
  }

  def bindPlugin[T <: Plugin : Manifest](): Unit = {
    val plugins = ScalaMultibinder.newSetBinder[Plugin.Factory[T]](binder)
    plugins.addBinding().to[Plugin.Factory[T]]
    bindFactory[Plugin, T, Plugin.Factory[T]]()
  }

  def bindFactory[I: Manifest, C <: I : Manifest, F: Manifest](): Unit = {
    import net.codingwell.scalaguice._
    install(new FactoryModuleBuilder()
      .implement(typeLiteral[I], typeLiteral[C])
      .build(typeLiteral[F]))
  }
})
  • 0
    Спасибо, я был близок к этому, но у меня не было общего типа на моей заводской черте, и поэтому Guice говорил мне, что я не могу связать каждый плагин, потому что он уже был связан. Это сработало отлично!
  • 0
    Кстати, я столкнулся с проблемой, которую вы упомянули с scala-guice и Multibinder ( github.com/codingwell/scala-guice/issues/29 ), но код в ссылочном запросе, на который вы ссылаетесь, исправил его. Спасибо!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню