将Guice多重绑定与辅助注入一起用于集合成员
我有一个 PluginManager
类,它使用Guice多重绑定功能接受 Set< Plugin>
.但是, PluginManager
具有一些运行时信息,需要将这些信息传递给 Plugin
构造函数.
I have a class PluginManager
which accepts a Set<Plugin>
using the Guice multi-bindings feature. However, the PluginManager
has some runtime information that needs to be passed to the Plugin
constructor.
这似乎是Guice辅助注入的完美用例,即我的 PluginManager
将注入 Set< PluginFactory>
,其中将运行时信息提供给每个工厂,从而产生必需的 Plugin
实例.
This seems to be a perfect use-case for Guice assisted injection i.e. my PluginManager
would have Set<PluginFactory>
injected, where the runtime information is provided to each factory, resulting in the required Plugin
instances.
但是我不知道在 Module
中使用的语法.多绑定器 addBinding
似乎没有任何功能可以连接 FactoryModuleBuilder
的结果.
I don't know the syntax to use in the Module
however. The multibinder addBinding
does not seem to have any facility to connect the result of FactoryModuleBuilder
.
我可以创建自己的自定义Factory实现并进行显然的多重绑定,但是有没有办法将multibinder与辅助注入结合起来?
I can create my own custom Factory implementations and multibind that obviously, but is there a way to combine multibinder with assisted inject?
我认为这为您提供了一个示例,可以准确地完成您想要的事情.请注意,scala的multibinder具有悬而未决的拉取请求,可让您在多个位置创建设置的活页夹.
I think this gives you an example to do exactly what you want. Please note that scala's multibinder has a pending pull request that allows you to create the set binder in multiple places.
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时),如下所示:
You can do a bunch of things depending on the style you want. For example you could make a generic addPlugin method (when a newer version of scala-guice is released) like this:
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]))
}
})