У меня есть класс PluginManager
который принимает Set<Plugin>
используя функцию Guis multi-bindings. Тем не менее, PluginManager
имеет некоторую информацию о времени выполнения, которая должна быть передана конструктору Plugin
.
Это, по-видимому, идеальный вариант использования для инъекций с помощью Guice, т.е. у моего PluginManager
бы установлен Set<PluginFactory>
, где информация о времени выполнения предоставляется на каждом заводе, в результате чего требуются экземпляры Plugin
.
Однако я не знаю, какой синтаксис использовать в Module
. У addBinding
нет никакого средства для подключения результата FactoryModuleBuilder
.
Я могу создать собственные пользовательские реализации Factory и multibind, которые, очевидно, но есть ли способ комбинировать мультиинжинер с вспомогательной инъекцией?
Я думаю, это дает вам пример, чтобы сделать именно то, что вы хотите. Обратите внимание, что 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]))
}
})