1 /** 2 * Skadi.d Web Framework 3 * 4 * Forked from: https://github.com/mbierlee/poodinis 5 * Authors: Mike Bierlee, Faianca 6 * Copyright: Copyright (c) 2015 Mike Bierlee, Faianca 7 * License: MIT License, see LICENSE 8 */ 9 module skadi.container.registration; 10 11 import skadi.container.interfaces; 12 13 debug { 14 import std.stdio; 15 import std.string; 16 } 17 18 class Registration 19 { 20 private TypeInfo _registeredType = null; 21 private TypeInfo_Class _instantiatableType = null; 22 private Registration linkedRegistration; 23 24 public @property registeredType() 25 { 26 return _registeredType; 27 } 28 29 public @property instantiatableType() 30 { 31 return _instantiatableType; 32 } 33 34 public CreationScope registationScope = null; 35 36 this(TypeInfo registeredType, TypeInfo_Class instantiatableType) 37 { 38 this._registeredType = registeredType; 39 this._instantiatableType = instantiatableType; 40 } 41 42 public Object getInstance(InstantiationContext context = new InstantiationContext()) 43 { 44 if (linkedRegistration !is null) { 45 return linkedRegistration.getInstance(context); 46 } 47 48 49 if (registationScope is null) { 50 throw new NoScopeDefinedException(registeredType); 51 } 52 53 return registationScope.getInstance(); 54 } 55 56 public Registration linkTo(Registration registration) 57 { 58 this.linkedRegistration = registration; 59 return this; 60 } 61 } 62 63 class NoScopeDefinedException : Exception 64 { 65 this(TypeInfo type) { 66 super("No scope defined for registration of type " ~ type.toString()); 67 } 68 } 69 70 71 class NullScope : CreationScope 72 { 73 public Object getInstance() 74 { 75 debug(skadiVerbose) { 76 writeln("DEBUG: No instance created (NullScope)"); 77 } 78 return null; 79 } 80 } 81 82 class SingleInstanceScope : CreationScope 83 { 84 TypeInfo_Class instantiatableType = null; 85 Object instance = null; 86 87 this(TypeInfo_Class instantiatableType) { 88 this.instantiatableType = instantiatableType; 89 } 90 91 public Object getInstance() 92 { 93 if (instance is null) { 94 debug(skadiVerbose) { 95 writeln(format("DEBUG: Creating new instance of type %s (SingleInstanceScope)", instantiatableType.toString())); 96 } 97 instance = instantiatableType.create(); 98 } else { 99 debug(skadiVerbose) { 100 writeln(format("DEBUG: Existing instance returned of type %s (SingleInstanceScope)", instantiatableType.toString())); 101 } 102 } 103 104 105 return instance; 106 } 107 } 108 109 /** 110 * Scopes registrations to return the same instance every time a given registration is resolved. 111 * 112 * Effectively makes the given registration a singleton. 113 */ 114 public Registration singleInstance(Registration registration) 115 { 116 registration.registationScope = new SingleInstanceScope(registration.instantiatableType); 117 return registration; 118 } 119 120 class NewInstanceScope : CreationScope 121 { 122 TypeInfo_Class instantiatableType = null; 123 124 this(TypeInfo_Class instantiatableType) { 125 this.instantiatableType = instantiatableType; 126 } 127 128 public Object getInstance() { 129 debug(skadiVerbose) { 130 writeln(format("DEBUG: Creating new instance of type %s (SingleInstanceScope)", instantiatableType.toString())); 131 } 132 return instantiatableType.create(); 133 } 134 } 135 136 /** 137 * Scopes registrations to return a new instance every time the given registration is resolved. 138 */ 139 public Registration newInstance(Registration registration) 140 { 141 registration.registationScope = new NewInstanceScope(registration.instantiatableType); 142 return registration; 143 } 144 145 class ExistingInstanceScope : CreationScope 146 { 147 Object instance = null; 148 149 this(Object instance) { 150 this.instance = instance; 151 } 152 153 public Object getInstance() { 154 debug(skadiVerbose) { 155 writeln("DEBUG: Existing instance returned (ExistingInstanceScope)"); 156 } 157 return instance; 158 } 159 } 160 161 /** 162 * Scopes registrations to return the given instance every time the given registration is resolved. 163 */ 164 public Registration existingInstance(Registration registration, Object instance) 165 { 166 registration.registationScope = new ExistingInstanceScope(instance); 167 return registration; 168 } 169 170 public string toConcreteTypeListString(Registration[] registrations) 171 { 172 auto concreteTypeListString = ""; 173 foreach (registration ; registrations) { 174 if (concreteTypeListString.length > 0) { 175 concreteTypeListString ~= ", "; 176 } 177 concreteTypeListString ~= registration.instantiatableType.toString(); 178 } 179 return concreteTypeListString; 180 } 181 182 class InstantiationContext {}