DI Binding to a subclass

258 views Asked by At

I'm wondering if it's possible to bind dependencies with following syntax:

bind [Environment[User, Authenticator]] to FakeEnvironment[User, SessionAuthenticator](testUser)

(this was taken from tests, actual binding in the Module is slightly more verbose)

where SessionAuthenticator has following signature:

case class SessionAuthenticator(val loginInfo : com.mohiva.play.silhouette.api.LoginInfo, ...)
    extends scala.AnyRef 
        with com.mohiva.play.silhouette.api.Authenticator 
        with scala.Product 
        with scala.Serializable {...}

and Authenticator:

 trait Authenticator extends scala.AnyRef {...}

But all I get is the following stacktrace during compilation:

[error] /home/mironor/projects/livrarium/test/controllers/CloudSpec.scala:22: overloaded method value to with alternatives:
[error]   [T <: com.mohiva.play.silhouette.api.Environment[services.User,com.mohiva.play.silhouette.api.Authenticator]](fn: => T)(implicit evidence$2: reflect.runtime.universe.TypeTag[T])scaldi.BoundHelper[T] <and>
[error]   (none: None.type)scaldi.BoundHelper[com.mohiva.play.silhouette.api.Environment[services.User,com.mohiva.play.silhouette.api.Authenticator]]
[error]  cannot be applied to (com.mohiva.play.silhouette.test.FakeEnvironment[services.User,com.mohiva.play.silhouette.impl.authenticators.SessionAuthenticator])
[error]       bind [Environment[User, Authenticator]] to FakeEnvironment[User, SessionAuthenticator](user)

This way I could choose which Authenticator to use only once in applicaiton's Module and inject it like this:

implicit val env = inject[Environment[User, Authenticator]]

instead of:

implicit val env = inject[Environment[User, SessionAuthenticator]]

What are my options?

1

There are 1 answers

1
tenshi On BEST ANSWER

It is possible to archive this with scaldi, but the problem is with the way Environment is defined and used. I assume (at least error tells me this) that Environment is invariant on both of it's type arguments. This is the problem, because you want to treat Environment[User, Authenticator] as a superclass of Environment[User, SessionAuthenticator]. It is not the case if both type arguments are defined as invariant. To fix this issue you can just make the second type argument of Environment covariant with +:

trait Environment[A, +B]

Theoretically it should fix the compile error you shown.