diff --git a/source/poodinis/autowire.d b/source/poodinis/autowire.d index e498c56..0aa4513 100644 --- a/source/poodinis/autowire.d +++ b/source/poodinis/autowire.d @@ -135,6 +135,9 @@ private void autowireMember(string member, size_t memberIndex, Type)(shared(Depe } else static if (is(typeof(attribute) == Value)) { enum key = attribute.key; injectValue!(member, memberIndex, key, false)(container, instance); + } else static if (is(typeof(attribute) == MandatoryValue)) { + enum key = attribute.key; + injectValue!(member, memberIndex, key, true)(container, instance); } } } diff --git a/source/poodinis/valueinjection.d b/source/poodinis/valueinjection.d index 4910bb8..8d649a7 100644 --- a/source/poodinis/valueinjection.d +++ b/source/poodinis/valueinjection.d @@ -60,6 +60,32 @@ struct Value { string key; } +/** + * UDA used for marking class members which should be value-injected. + * + * When the injector throws a ValueNotAvailableException, it is re-thrown + * instead of being suppressed. + * + * A key must be supplied, which can be in any format depending on how + * a value injector reads it. + * + * Examples: + * --- + * class MyClass { + * @MandatoryValue("general.valueWhichShouldBeThere") + * private int number; + * } + * --- + */ +struct MandatoryValue { + /** + * The textual key used to find the value by injectors. + * + * The format is injector-specific. + */ + string key; +} + /** * Interface which should be implemented by value injectors. * diff --git a/test/poodinis/valueinjectiontest.d b/test/poodinis/valueinjectiontest.d index 01e8039..89ff347 100644 --- a/test/poodinis/valueinjectiontest.d +++ b/test/poodinis/valueinjectiontest.d @@ -30,6 +30,11 @@ version(unittest) { int noms = 9; } + class ConfigWithMandatory { + @MandatoryValue("conf.mustbethere") + int nums; + } + // Test injection of values unittest { auto container = new shared DependencyContainer(); @@ -91,4 +96,38 @@ version(unittest) { auto instance = container.resolve!ConfigWithDefaults; assert(instance.noms == 9); } + + // Test mandatory injection of values which are available + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithMandatory; + + class IntInjector : ValueInjector!int { + public override int get(string key) { + return 7466; + } + } + + container.register!(ValueInjector!int, IntInjector); + + auto instance = container.resolve!ConfigWithMandatory; + assert(instance.nums == 7466); + } + + // Test mandatory injection of values which are not available + unittest { + auto container = new shared DependencyContainer(); + container.register!ConfigWithMandatory; + + class IntInjector : ValueInjector!int { + public override int get(string key) { + throw new ValueNotAvailableException(key); + } + } + + container.register!(ValueInjector!int, IntInjector); + + assertThrown!ResolveException(container.resolve!ConfigWithMandatory); + assertThrown!ValueInjectionException(autowire(container, new ConfigWithMandatory())); + } }