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