1 /++
2 Aedi, a dependency injection framework.
3 
4 Aedi is a dependency injection framework. It does provide a set of containers that do
5 IoC, and an interface to configure application components (structs, objects, etc.) managed by framework.
6 
7 Aim:
8 The aim of library is to provide a dependency injection solution that is
9 feature rich, easy to use, easy to learn, and easy to extend up to your needs.
10 
11 Usage:
12 The process of configuring components using Aedi consists of following steps:
13 
14 $(UL
15     $(LI Create a container )
16     $(LI Register an application component. )
17     $(LI Bind dependencies to it. )
18     $(LI Repeat process for other components. )
19     $(LI Boot container, and use components from it )
20     $(LI Shutdown container )
21 )
22 
23 Following code example shows how can a IoC container be configured and used:
24 
25 -------------------
26 module app;
27 
28 import aermicioi.aedi;
29 import std.stdio;
30 
31 /**
32 A struct that should be managed by container.
33 **/
34 @component
35 struct Color {
36     @setter(cast(ubyte) 255)
37     ubyte r;
38 
39     @setter(cast(ubyte) 10)
40     ubyte g;
41 
42     @setter(cast(ubyte) 10)
43     ubyte b;
44 }
45 
46 /**
47 Size of a car.
48 **/
49 @component // Register component using annotations
50 struct Size {
51 
52     @setter(200UL) // Set property to specific value
53     ulong width;
54 
55     @setter(150UL)
56     ulong height;
57 
58     @setter(500UL)
59     ulong length;
60 }
61 
62 /**
63 A class representing a car.
64 **/
65 @component
66 class Car {
67 
68     private {
69         Color color_; // Car color
70         Size size_; // Car size
71     }
72 
73     public {
74 
75         @constructor(lref!Size) // Construct component using Size component from IoC container.
76         this(Size size) {
77             this.size_ = size;
78         }
79 
80         @property {
81 
82             @autowired // Autowire property with a component from IoC container
83             Car color(Color color) @safe nothrow {
84             	this.color_ = color;
85 
86             	return this;
87             }
88 
89             inout(Color) color() @safe nothrow pure inout {
90                 return this.color_;
91             }
92 
93             inout(Size) size() @safe nothrow pure inout {
94                 return this.size_;
95             }
96         }
97     }
98 }
99 
100 class Mercedes : Car {
101     this(Size s) {
102         super(s);
103     }
104 }
105 
106 class Volkswagen : Car {
107     this(Size s) {
108         super(s);
109     }
110 }
111 
112 @component // Configuration component that creates components managed by container.
113 class Manufacturer {
114 
115     public {
116         @component // Add component to container that is constructed by Manufacturer.
117         Mercedes makeMercedes() {
118             return new Mercedes(Size(201, 150, 501));
119         }
120     }
121 }
122 
123 void print(Car car) {
124     writeln("You bought a new ", car.classinfo.name, " with following specs:");
125     writeln("Size:\t", car.size());
126     writeln("Color:\t", car.color());
127 }
128 
129 void main() {
130     auto container = singleton(); // 1. Create container that will manage a color
131     scope(exit) container.terminate(); // 6. Shutdown the container
132 
133     with (container.configure) {
134 
135         register!Volkswagen // 2. Register color into container.
136             .construct(Size(100, 200, 500))
137             .set!"color"("blue".lref); // 3. Bind blue color from container
138 
139         register!Color("blue")
140             .set!"r"(cast(ubyte) 0)
141             .set!"g"(cast(ubyte) 0)
142             .set!"b"(cast(ubyte) 255);
143     }
144 
145     container.scan!app; // 4. Scan app module, and register all annotated components.
146 
147     container.instantiate(); // 5. Start the IoC container.
148 
149     container.locate!Car.print; // 5. Use component from IoC container.
150     container.locate!Mercedes.print;
151     container.locate!Volkswagen.print;
152 }
153 -------------------
154 
155 License:
156 	Boost Software License - Version 1.0 - August 17th, 2003
157 
158 	Permission is hereby granted, free of charge, to any person or organization
159 	obtaining a copy of the software and accompanying documentation covered by
160 	this license (the "Software") to use, reproduce, display, distribute,
161 	execute, and transmit the Software, and to prepare derivative works of the
162 	Software, and to permit third-parties to whom the Software is furnished to
163 	do so, all subject to the following:
164 
165 	The copyright notices in the Software and this entire statement, including
166 	the above license grant, this restriction and the following disclaimer,
167 	must be included in all copies of the Software, in whole or in part, and
168 	all derivative works of the Software, unless such copies or derivative
169 	works are solely in the form of machine-executable object code generated by
170 	a source language processor.
171 
172 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
173 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
174 	FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
175 	SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
176 	FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
177 	ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
178 	DEALINGS IN THE SOFTWARE.
179 
180 Authors:
181 	aermicioi
182 ++/
183 
184 module minimal;
185 
186 import aermicioi.aedi;
187 import std.stdio;
188 
189 /**
190 A struct that should be managed by container.
191 **/
192 @component
193 struct Color {
194     @setter(cast(ubyte) 255)
195     ubyte r;
196 
197     @setter(cast(ubyte) 10)
198     ubyte g;
199 
200     @setter(cast(ubyte) 10)
201     ubyte b;
202 }
203 
204 /**
205 Size of a car.
206 **/
207 @component // Register component using annotations
208 struct Size {
209 
210     @setter(200UL) // Set property to specific value
211     ulong width;
212 
213     @setter(150UL)
214     ulong height;
215 
216     @setter(500UL)
217     ulong length;
218 }
219 
220 /**
221 A class representing a car.
222 **/
223 @component
224 class Car {
225 
226     private {
227         Color color_; // Car color
228         Size size_; // Car size
229     }
230 
231     public {
232 
233         @constructor(lref!Size) // Construct component using Size component from IoC container.
234         this(Size size) {
235             this.size_ = size;
236         }
237 
238         @property {
239 
240             @autowired // Autowire property with a component from IoC container
241             Car color(Color color) @safe nothrow {
242             	this.color_ = color;
243 
244             	return this;
245             }
246 
247             inout(Color) color() @safe nothrow pure inout {
248                 return this.color_;
249             }
250 
251             inout(Size) size() @safe nothrow pure inout {
252                 return this.size_;
253             }
254         }
255     }
256 }
257 
258 class Mercedes : Car {
259     this(Size s) {
260         super(s);
261     }
262 }
263 
264 class Volkswagen : Car {
265     this(Size s) {
266         super(s);
267     }
268 }
269 
270 @component // Configuration component that creates components managed by container.
271 class Manufacturer {
272 
273     public {
274         @component // Add component to container that is constructed by Manufacturer.
275         Mercedes makeMercedes() {
276             return new Mercedes(Size(201, 150, 501));
277         }
278     }
279 }
280 
281 void print(Car car) {
282     writeln("You bought a new ", car.classinfo.name, " with following specs:");
283     writeln("Size:\t", car.size());
284     writeln("Color:\t", car.color());
285 }
286 
287 void main() {
288     auto container = singleton(); // 1. Create container that will manage a color
289     scope(exit) container.terminate(); // 6. Shutdown the container
290 
291     with (container.configure) {
292 
293         register!Volkswagen // 2. Register color into container.
294             .construct(Size(100, 200, 500))
295             .set!"color"("blue".lref); // 3. Bind blue color from container
296 
297         register!Color("blue")
298             .set!"r"(cast(ubyte) 0)
299             .set!"g"(cast(ubyte) 0)
300             .set!"b"(cast(ubyte) 255);
301     }
302 
303     container.scan!minimal; // 4. Scan minimal module, and register all annotated components.
304 
305     container.instantiate(); // 5. Start the IoC container.
306 
307     container.locate!Car.print; // 5. Use component from IoC container.
308     container.locate!Mercedes.print;
309     container.locate!Volkswagen.print;
310 }