Advertisement
Guest User

Untitled

a guest
Jun 27th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.47 KB | None | 0 0
  1. import scala.reflect.runtime.{universe => ru}
  2. import ru._
  3. import extensions.MapExtension._
  4.  
  5. class RegisterConfig[TSource: TypeTag](container: Container){
  6. def as[TTrait >: TSource : TypeTag] = {
  7. container.typeTable += typeOf[TTrait] -> typeOf[TSource]
  8. container
  9. }
  10. }
  11.  
  12. class InstanceConfig[TSource: TypeTag](container: Container, instance: TSource){
  13. def as[TTrait >: TSource : TypeTag] = {
  14. container.typeTable += typeOf[TTrait] -> typeOf[TSource]
  15. container.instances += typeOf[TTrait] -> instance
  16. container
  17. }
  18. }
  19.  
  20. class ContainerConfig(container: Container) {
  21. def register[TSource: TypeTag] = new RegisterConfig(container)
  22.  
  23. def instance[TSource: TypeTag](instance: TSource) = new InstanceConfig(container, instance)
  24. }
  25.  
  26. class Container {
  27. var typeTable = Map[Type, Type]()
  28. var instances = Map[Type, Any]()
  29.  
  30. def config() = new ContainerConfig(this)
  31.  
  32. def resolve[TSource: TypeTag] = resolveDynamic(typeOf[TSource]).asInstanceOf[TSource]
  33.  
  34. private def resolveDynamic(requestedType: Type) = {
  35. val resultType = typeTable.getOrElseWithCompare(requestedType, requestedType, (x, y) => x =:= y)
  36.  
  37. val instance = instances.getOrElseWithCompare(resultType, createInstance(resultType), (x, y) => x =:= y)
  38.  
  39. instances += resultType -> instance
  40.  
  41. instance
  42. }
  43.  
  44. private def createInstance(tpe: Type): Any = {
  45. val mirror: ru.Mirror = ru.runtimeMirror(getClass.getClassLoader)
  46. val clsSym: ru.ClassSymbol = tpe.typeSymbol.asClass
  47. val clsMirror: ru.ClassMirror = mirror.reflectClass(clsSym)
  48. val constructorSym: ru.MethodSymbol = tpe.decl(ru.termNames.CONSTRUCTOR).asMethod
  49. val constructorParameterTypes = constructorSym.paramLists.head.map(x => x.typeSignature)
  50. // Recursive step
  51. val params = constructorParameterTypes.map(x => resolveDynamic(x)).toArray
  52. // Passing `params` does not work! I get an exception here ...
  53. val constructorMirror: ru.MethodMirror = clsMirror.reflectConstructor(constructorSym)
  54. val instance = constructorMirror(params)
  55. instance
  56. }
  57. }
  58.  
  59. import org.scalatest.FlatSpec
  60.  
  61. trait TestTrait
  62. class TestClass extends TestTrait
  63. class TestRecClass(x : TestTrait)
  64.  
  65. class ContainerTest extends FlatSpec {
  66.  
  67. "Given Trait" should "return instance (with recursion)" in {
  68. val container = new Container()
  69. .config()
  70. .register[TestClass]
  71. .as[TestTrait]
  72.  
  73. val instance = container.resolve[TestRecClass]
  74.  
  75. assert(instance match {
  76. case _: TestRecClass => true
  77. case null => false
  78. })
  79. }
  80. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement