Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import scala.reflect.runtime.{universe => ru}
- import ru._
- import extensions.MapExtension._
- class RegisterConfig[TSource: TypeTag](container: Container){
- def as[TTrait >: TSource : TypeTag] = {
- container.typeTable += typeOf[TTrait] -> typeOf[TSource]
- container
- }
- }
- class InstanceConfig[TSource: TypeTag](container: Container, instance: TSource){
- def as[TTrait >: TSource : TypeTag] = {
- container.typeTable += typeOf[TTrait] -> typeOf[TSource]
- container.instances += typeOf[TTrait] -> instance
- container
- }
- }
- class ContainerConfig(container: Container) {
- def register[TSource: TypeTag] = new RegisterConfig(container)
- def instance[TSource: TypeTag](instance: TSource) = new InstanceConfig(container, instance)
- }
- class Container {
- var typeTable = Map[Type, Type]()
- var instances = Map[Type, Any]()
- def config() = new ContainerConfig(this)
- def resolve[TSource: TypeTag] = resolveDynamic(typeOf[TSource]).asInstanceOf[TSource]
- private def resolveDynamic(requestedType: Type) = {
- val resultType = typeTable.getOrElseWithCompare(requestedType, requestedType, (x, y) => x =:= y)
- val instance = instances.getOrElseWithCompare(resultType, createInstance(resultType), (x, y) => x =:= y)
- instances += resultType -> instance
- instance
- }
- private def createInstance(tpe: Type): Any = {
- val mirror: ru.Mirror = ru.runtimeMirror(getClass.getClassLoader)
- val clsSym: ru.ClassSymbol = tpe.typeSymbol.asClass
- val clsMirror: ru.ClassMirror = mirror.reflectClass(clsSym)
- val constructorSym: ru.MethodSymbol = tpe.decl(ru.termNames.CONSTRUCTOR).asMethod
- val constructorParameterTypes = constructorSym.paramLists.head.map(x => x.typeSignature)
- // Recursive step
- val params = constructorParameterTypes.map(x => resolveDynamic(x)).toArray
- // Passing `params` does not work! I get an exception here ...
- val constructorMirror: ru.MethodMirror = clsMirror.reflectConstructor(constructorSym)
- val instance = constructorMirror(params)
- instance
- }
- }
- import org.scalatest.FlatSpec
- trait TestTrait
- class TestClass extends TestTrait
- class TestRecClass(x : TestTrait)
- class ContainerTest extends FlatSpec {
- "Given Trait" should "return instance (with recursion)" in {
- val container = new Container()
- .config()
- .register[TestClass]
- .as[TestTrait]
- val instance = container.resolve[TestRecClass]
- assert(instance match {
- case _: TestRecClass => true
- case null => false
- })
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement