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 }