Closed Maatary closed 10 years ago
Hmm. This might take some thinking.
Per your example; you can do exactly that.
object T {
def main(args: Array[String]) {
val a = Guice.createInjector(new Module).instance[A]
println(a.string)
println(a.b)
}
class A @Inject() (val string: Option[String], val b: Option[B])
class B
class Module extends ScalaModule {
def configure() {
bind[Option[String]].toInstance(Some("Hello World"))
bind[Option[B]].toInstance(None)
}
}
}
Now... if you're talking about truly optional dependencies; you can see that Guice barely supports it. They suggest to create a container class. Thus, it seems to be possible to create a generic optional provider class such as this:
object T {
def main(args: Array[String]) {
val a = Guice.createInjector(new Module).instance[A]
println(a.string)
println(a.b)
}
class A @Inject() (val string: Option[String], val b: Option[B])
class B
class Module extends ScalaModule {
def configure() {
binder.requireExplicitBindings() // Guice will try to create anything it can such as an instance of B even if unbound
bind[A].asEagerSingleton()
bind[String].toInstance("Hello World")
// We must register providers for each optional injection
bindOpt[String]
bindOpt[B]
}
private[this] def bindOpt[T: Manifest] = bind[Option[T]].toProvider[OptionalProvider[T]]
}
class OptionalProvider[T] @Inject() extends Provider[Option[T]] {
@Inject(optional = true)
val t: T = null.asInstanceOf[T]
def get(): Option[T] = Option(t)
}
}
And the downside is, obviously, that you have to pre-register every optional thing you might inject. Another downside is that any annotated constraints on the T can't be automagically picked up (like an @Named
Option
injection).
Unfortunately, Guice was not written with the idea of extending it via additional resolvers (akin to the way Jackson works). So it is not possible for any magic to automatically create Option[T]
injections for any T
.
Understood.
Many thanks such detailed and nit explanation. Appreciated.
On Monday, December 30, 2013, Nate Bauernfeind wrote:
Per your example; you can do exactly that.
object T { def main(args: Array[String]) { val a = Guice.createInjector(new Module).instance[A] println(a.string) println(a.b) }
class A @Inject() (val string: Option[String], val b: Option[B]) class B
class Module extends ScalaModule { def configure() { bind[Option[String]].toInstance(Some("Hello World")) bind[Option[B]].toInstance(None) } }}
Now... if you're talking about truly optional dependencies; you can see that Guice barely supports ithttps://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_can_I_inject_optional_parameters_into_a_constructor?. They suggest to create a container class. Thus, it seems to be possible to create a generic optional provider class such as this:
object T { def main(args: Array[String]) { val a = Guice.createInjector(new Module).instance[A] println(a.string) println(a.b) }
class A @Inject() (val string: Option[String], val b: Option[B]) class B
class Module extends ScalaModule { def configure() { binder.requireExplicitBindings() // Guice will try to create anything it can such as an instance of B even if unbound bind[A].asEagerSingleton() bind[String].toInstance("Hello World")
// We must register providers for each optional injection bindOpt[String] bindOpt[B] } private[this] def bindOpt[T: Manifest] = bind[Option[T]].toProvider[OptionalProvider[T]]
}
class OptionalProvider[T] @Inject() extends Provider[Option[T]] { @Inject(optional = true) val t: T = null.asInstanceOf[T] def get(): Option[T] = Option(t) }}
And the downside is, obviously, that you have to pre-register every optional thing you might inject. Another downside is that any annotated constraints on the T can't be automagically picked up (like an @Named Option injection).
Unfortunately, Guice was not written with the idea of extending it via additional resolvers (akin to the way Jackson works). So it is not possible for any magic to automatically create Option[T] injections for any T.
— Reply to this email directly or view it on GitHubhttps://github.com/codingwell/scala-guice/issues/22#issuecomment-31332472 .
Should revisit this now that https://github.com/google/guice/commit/842f351c4b2b3b0a90d9f3bcf164d8fd19aede6c has landed
bind([Option [T]]).instance[Some(T)]