1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi.configurer.register.container; 31 32 import aermicioi.aedi.container; 33 import std.traits; 34 import std.meta; 35 import aermicioi.aedi.util.traits; 36 37 @safe: 38 39 /** 40 Create a singleton container 41 42 Returns: 43 SingletonContainer 44 **/ 45 auto singleton() { 46 return new SingletonContainer(); 47 } 48 49 /** 50 Create a prototype container 51 52 Returns: 53 PrototypeContainer 54 **/ 55 auto prototype() { 56 return new PrototypeContainer(); 57 } 58 59 /** 60 Create a container for values 61 62 Returns: 63 ValueContainer 64 **/ 65 auto values() { 66 return new ValueContainer(); 67 } 68 69 /** 70 Wrap up a container into switchable container. 71 72 Wraps up a container to provide switching capabilites to it. 73 74 Params: 75 container = container to wrap up in switchable container 76 77 Returns: 78 SwitchableContainer!T 79 **/ 80 auto switchable(T : Container)(auto ref T container) { 81 return (new SwitchableContainer!T()).decorated(container); 82 } 83 84 /** 85 Wrap up a container into subscribable container. 86 87 Wraps up a container to provide events to subscribe to. 88 89 Params: 90 container = container to wrap up in subscribable container 91 92 Returns: 93 SubscribableContainer!T 94 **/ 95 auto subscribable(T : Container)(auto ref T container) { 96 return (new SubscribableContainer!T()).decorated(container); 97 } 98 99 /** 100 Wrap up a container into a type based container. 101 102 Wraps up container into a container that adds capability to 103 search for a component based on it's type, or implemented 104 hierarchy of classes and interfaces. 105 106 Params: 107 container = container to wrap up in typed container 108 109 Returns: 110 TypeBasedContainer!T 111 **/ 112 auto typed(T : Container)(auto ref T container) { 113 return (new TypeBasedContainer!T()).decorated(container); 114 } 115 116 /** 117 Wrap up a container into aliasing container. 118 119 Wraps up container into aliasing container which provides 120 capabilities to alias identity of components in original container. 121 122 Params: 123 container = container to wrap up in aliasing container 124 125 Returns: 126 AliasingContainer!T 127 **/ 128 auto aliasing(T)(auto ref T container) { 129 return (new AliasingContainer!T()).decorated(container); 130 } 131 132 /** 133 Wrap up a container into a deferring container. 134 135 Wraps up container into a deferring container which executes deferred actions 136 when a component from it is requested from exterior and not interior of container. 137 Therefore with help of it, is possible to solve circular dependency errors by deferring 138 setting a dependency at a later time when dependents are fully constructed. 139 140 Params: 141 container = container to wrap up in defferred container 142 deferredExecutionerIdentity = identity of container for defferred actions that will be used by contained factories if needed. 143 144 Returns: 145 DefferedContainer!T 146 **/ 147 auto deferred(T)(auto ref T container, string deferredExecutionerIdentity) { 148 return (new DeferredContainer!T(container, deferredExecutionerIdentity)); 149 } 150 151 /** 152 ditto 153 **/ 154 auto deferred(T)(auto ref T container) { 155 return (new DeferredContainer!T(container)); 156 } 157 158 /** 159 Wrap up container into gc registering container. 160 161 Wrap up container into gc registering container, that will automatically 162 register all created components by it into garbage collector for proper 163 scanning. 164 165 Params: 166 container = container to decorate with gc component registration. 167 168 Returns: 169 GcRegisteringContainer!T 170 **/ 171 auto gcRegistered(T)(auto ref T container) { 172 return (new GcRegisteringContainer!T).decorated(container); 173 } 174 175 /** 176 Wraps up several containers into one. 177 178 Params: 179 containers = a list of containers to be used together 180 181 Returns: 182 TupleContainer!T 183 **/ 184 auto container(T...)(T containers) 185 if (allSatisfy!(partialSuffixed!(isDerived, Container), T)) { 186 return new TupleContainer!T(containers); 187 } 188 189 /** 190 Wraps up several containers into one. 191 192 Params: 193 managed = first container managed by aggregate one 194 identity = identity of container by which it is possible to identify it 195 manageds = a set of containers in pairs of (managed, identity) 196 197 Returns: 198 TupleContainer!T 199 **/ 200 auto aggregate(T...)(Container managed, string identity, T manageds) { 201 AggregateContainer container = new AggregateContainer; 202 203 return container.aggregate(managed, identity, manageds); 204 } 205 206 /** 207 Wrap up container into describing container. 208 209 Wrap up container into describing container, that 210 provides description of itself and underlying components 211 through a set of Describer components. 212 213 Params: 214 componentDescriber = describer for components container manages 215 fallbackComponentDescriber = fallback describer in case componentDescriber fails to describe particular component 216 containerDescriber = describer used to describe container itself 217 218 Returns: 219 DescribingContainer!T 220 **/ 221 auto describing(T : Container)(T container, Describer!() componentDescriber, Describer!() containerDescriber, Describer!() fallbackComponentDescriber) { 222 return new DescribingContainer!T(container, componentDescriber, containerDescriber, fallbackComponentDescriber); 223 } 224 225 /** 226 ditto 227 **/ 228 auto describing(T : Container)(T container, Describer!() componentDescriber, Describer!() containerDescriber) { 229 return new DescribingContainer!T(container, componentDescriber, containerDescriber); 230 } 231 232 /** 233 ditto 234 **/ 235 auto describing(T : Container)(T container, Describer!() componentDescriber, string title, string description) { 236 return new DescribingContainer!T(container, componentDescriber, new StaticDescriber!()(typeid(T).toString, title, description)); 237 } 238 239 /** 240 ditto 241 **/ 242 auto describing(T : Container)(T container, string title = null, string description = null) { 243 return new DescribingContainer!T(container, new IdentityDescriber!(), new StaticDescriber!()(typeid(T).toString, title, description)); 244 } 245 246 /** 247 A prebuilt container with all features enabled. 248 249 Params: 250 title = container title. 251 description = container description. 252 253 Returns: 254 Prebuild container from singleton, prototype, and values containers. 255 **/ 256 auto application(string title, string description) { 257 return aggregate( 258 singleton.typed, "singleton", 259 prototype.typed, "prototype", 260 values, "parameters" 261 ) 262 .aliasing 263 .gcRegistered 264 .deferred 265 .describing(title, description) 266 .subscribable; 267 } 268 269 private { 270 271 auto aggregate(T...)(AggregateContainer container, Container managed, string identity, T manageds) { 272 container.set(managed, identity); 273 274 static if (T.length > 1) { 275 container.aggregate(manageds); 276 } 277 return container; 278 } 279 }