Created
July 18, 2013 16:06
-
-
Save fanf/6030588 to your computer and use it in GitHub Desktop.
Simple, Static Scala dependency injection with Shapeless
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package test_shapeless | |
object DI { | |
import shapeless._ | |
trait Injecter[L <: HList, A] { | |
def apply(l: L) : A | |
} | |
trait InjecterAux[L <: HList, A] { | |
def apply(l: L) : A | |
} | |
object Injecter { | |
implicit def injecter[L <: HList, A0](implicit injecter: InjecterAux[L, A0]) = new Injecter[L,A0] { | |
def apply(l:L) : A0 = injecter(l) | |
} | |
} | |
object InjecterAux { | |
implicit def foo[L <: HList, A, Out0 <: HList] | |
(implicit subtypeUnifier: SubtypeUnifierAux[L, A, Out0], filter: FilterAux[Out0, A, A :: HNil]) = | |
new InjecterAux[L,A] { | |
def apply(l:L) : A = filter(subtypeUnifier(l)).head | |
} | |
} | |
implicit class Injector[L <: HList](l:L) { | |
def inject[A](implicit injecter: Injecter[L,A]) : A = injecter(l) | |
} | |
} | |
object DependencyInjectionTest extends App { | |
import shapeless._ | |
trait ServiceOneImpl { def hello : String } | |
class ServiceOneImpl_0 extends ServiceOneImpl { val hello = "impl_0" } | |
trait ServiceMultiImpl { def hello: String } | |
class ServiceMultiImpl_1 extends ServiceMultiImpl { val hello = "impl_1"} | |
class ServiceMultiImpl_2 extends ServiceMultiImpl { val hello = "impl_2"} | |
trait Marker | |
val register = | |
(new ServiceOneImpl_0) :: | |
(new ServiceMultiImpl_1) :: | |
(new ServiceMultiImpl_2 with Marker) :: | |
HNil | |
implicit class Uniqueable[L <: HList](l: L) { | |
def unique[A](implicit filter: FilterAux[L, A, A :: HNil]) = { | |
filter(l).head | |
} | |
} | |
//implementation work | |
val s1 = register.unique[ServiceOneImpl_0] | |
println(s1.hello) //impl_0 | |
val s2 = register.unifySubtypes[ServiceOneImpl].unique[ServiceOneImpl] | |
println(s2.hello) //impl_0 | |
val s3 = register.unifySubtypes[ServiceMultiImpl with Marker].unique[ServiceMultiImpl with Marker] | |
println(s3.hello) //impl_2 | |
import DI._ | |
val s4 = register.inject[ServiceOneImpl_0] | |
println(s4.hello) //impl_0 | |
val s5 = register.inject[ServiceOneImpl] | |
println(s5.hello) //impl_0 | |
val s6 = register.inject[ServiceMultiImpl with Marker] | |
println(s6.hello) //impl_2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment