1 module aermicioi.aedi.container.deferred_container; 2 3 import aermicioi.aedi.container.container; 4 import aermicioi.aedi.storage.decorator; 5 import aermicioi.aedi.storage.alias_aware; 6 import aermicioi.aedi.factory.deferring_factory; 7 import aermicioi.aedi.factory.factory; 8 import aermicioi.aedi.storage.storage; 9 import aermicioi.aedi.storage.locator; 10 import aermicioi.aedi.factory.reference : RuntimeReference, resolve; 11 12 import std.meta; 13 import std.traits; 14 import aermicioi.aedi.util.traits; 15 16 /** 17 Decorating container that executes deffered tasks after a request is served from exterior. 18 This decorated will inherit following interfaces only and only if the 19 T also implements them: 20 $(OL 21 $(LI Storage!(ObjectFactory, string)) 22 $(LI AliasAware!string) 23 $(LI FactoryLocator) 24 ) 25 Decorated container must implement following interfaces: 26 $(OL 27 $(LI Container) 28 $(LI MutableDecorator!T) 29 $(LI Subscribable!ContainerInstantiationEventType) 30 $(LI Decorator!Container) 31 ) 32 33 Params: 34 T = The decorated that switchable decorated will decorate. 35 **/ 36 template DeferredContainer(T) 37 { 38 39 /** 40 Set which the switchable container will decorate for T. By default 41 Locator!() and Subscribable!ContainerInstantiationEventType is included. 42 **/ 43 alias InheritanceSet = NoDuplicates!(Filter!( 44 templateOr!( 45 partialSuffixed!( 46 isDerived, 47 Storage!(ObjectFactory, string) 48 ), 49 partialSuffixed!( 50 isDerived, 51 AliasAware!string 52 ), 53 partialSuffixed!( 54 isDerived, 55 FactoryLocator!ObjectFactory 56 ) 57 ), 58 InterfacesTuple!T), 59 Container, 60 Decorator!Container 61 ); 62 63 @safe class DeferredContainer : InheritanceSet 64 { 65 private 66 { 67 DeferralContext context; 68 const string contextIdentity; 69 } 70 71 public 72 { 73 74 /** 75 Default constructor for DefferedContainer 76 **/ 77 this(T container) 78 { 79 this.decorated = container; 80 context = new DeferralContext(); 81 contextIdentity = typeid(DeferralContext).toString(); 82 } 83 84 this(T container, string contextIdentity) { 85 this.decorated = container; 86 context = new DeferralContext(); 87 this.contextIdentity = contextIdentity; 88 } 89 90 mixin MutableDecoratorMixin!T; 91 92 static if (is(T : Storage!(Type, Id), Type, Id)) { 93 94 mixin StorageMixin!(typeof(this)); 95 } 96 97 static if (is(T : AliasAware!(X), X)) { 98 99 mixin AliasAwareMixin!(typeof(this)); 100 } 101 102 static if (is(T : FactoryLocator!(Z), Z)) { 103 104 mixin FactoryLocatorMixin!(typeof(this)); 105 } 106 107 /** 108 Get object created by a factory identified by key 109 110 Params: 111 key = identity of factory 112 Returns: 113 Object 114 **/ 115 Object get(string key) 116 { 117 if (key == contextIdentity) { 118 return context; 119 } 120 121 Object result = this.decorated.get(key); 122 123 if (context.pending) { 124 context.execute; 125 } 126 127 return result; 128 } 129 130 /** 131 Check if an object factory for it exists in container. 132 133 Params: 134 key = identity of factory 135 Returns: 136 bool 137 **/ 138 bool has(in string key) inout 139 { 140 if (key == this.contextIdentity) { 141 return true; 142 } 143 144 return this.decorated_.has(key); 145 } 146 147 mixin ContainerMixin!(typeof(this)); 148 } 149 } 150 }