1 /**
2  * This module contains facilities to support value injection. Actual injection is done by the
3  * autowiring mechanism.
4  *
5  * Authors:
6  *  Mike Bierlee, m.bierlee@lostmoment.com
7  * Copyright: 2014-2023 Mike Bierlee
8  * License:
9  *  This software is licensed under the terms of the MIT license.
10  *  The full terms of the license can be found in the LICENSE file.
11  */
12 module poodinis.valueinjection;
13 
14 import std.string : format;
15 import std.exception : basicExceptionCtors;
16 
17 /**
18  * Thrown when something goes wrong during value injection.
19  */
20 class ValueInjectionException : Exception {
21     mixin basicExceptionCtors;
22 }
23 
24 /**
25  * Thrown by injectors when the value with the given key cannot be found.
26  */
27 class ValueNotAvailableException : Exception {
28     this(string key) {
29         super(format("Value for key %s is not available", key));
30     }
31 
32     this(string key, Throwable cause) {
33         super(format("Value for key %s is not available", key), cause);
34     }
35 }
36 
37 /**
38  * UDA used for marking class members which should be value-injected.
39  *
40  * A key must be supplied, which can be in any format depending on how
41  * a value injector reads it.
42  *
43  * When the injector throws a ValueNotAvailableException, the value is
44  * not injected and will keep its original assignment.
45  *
46  * Examples:
47  * ---
48  * class MyClass {
49  *     @Value("general.importantNumber")
50  *     private int number = 8;
51  * }
52  * ---
53  */
54 struct Value {
55     /**
56      * The textual key used to find the value by injectors.
57      *
58      * The format is injector-specific.
59      */
60     string key;
61 }
62 
63 /**
64  * UDA used for marking class members which should be value-injected.
65  *
66  * When the injector throws a ValueNotAvailableException, it is re-thrown
67  * instead of being suppressed.
68  *
69  * A key must be supplied, which can be in any format depending on how
70  * a value injector reads it.
71  *
72  * Examples:
73  * ---
74  * class MyClass {
75  *     @MandatoryValue("general.valueWhichShouldBeThere")
76  *     private int number;
77  * }
78  * ---
79  */
80 struct MandatoryValue {
81     /**
82      * The textual key used to find the value by injectors.
83      *
84      * The format is injector-specific.
85      */
86     string key;
87 }
88 
89 /**
90  * Interface which should be implemented by value injectors.
91  *
92  * Each value injector injects one specific type. The type can be any primitive
93  * type or that of a struct. While class types are also supported, value injectors
94  * are not intended for them.
95  *
96  * Note that value injectors are also autowired before being used. Values within dependencies of
97  * a value injector are not injected. Neither are values within the value injector itself.
98  *
99  * Value injection is not supported for constructor injection.
100  *
101  * Examples:
102  * ---
103  * class MyIntInjector : ValueInjector!int {
104  *     public override int get(string key) { ... }
105  * }
106  *
107  * // In order to make the container use your injector, register it by interface:
108  * container.register!(ValueInjector!int, MyIntInjector);
109  * ---
110  */
111 interface ValueInjector(Type) {
112     /**
113      * Get a value from the injector by key.
114      *
115      * The key can have any format. Generally you are encouraged
116      * to accept a dot separated path, for example: server.http.port
117      *
118      * Throws: ValueNotAvailableException when the value for the given key is not available for any reason
119      */
120     Type get(string key);
121 }