Make it clear when a value injector is missing

This commit is contained in:
Mike Bierlee 2016-12-11 00:53:21 +01:00
parent 4954979574
commit 9eb3a89695
4 changed files with 49 additions and 7 deletions

View file

@ -206,10 +206,14 @@ private QualifierType createOrResolveInstance(MemberType, QualifierType, bool cr
private void injectValue(string member, size_t memberIndex, string key, Type)(shared(DependencyContainer) container, Type instance) {
alias MemberType = typeof(Type.tupleof[memberIndex]);
auto injector = container.resolve!(ValueInjector!MemberType);
instance.tupleof[memberIndex] = injector.get(key);
debug(poodinisVerbose) {
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
try {
auto injector = container.resolve!(ValueInjector!MemberType);
instance.tupleof[memberIndex] = injector.get(key);
debug(poodinisVerbose) {
printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key);
}
} catch (ResolveException e) {
throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s: value injector is missing for this type.", typeid(MemberType), typeid(Type), member));
}
}

View file

@ -25,6 +25,7 @@ import poodinis.registration;
import poodinis.autowire;
import poodinis.context;
import poodinis.factory;
import poodinis.valueinjection;
/**
* Exception thrown when errors occur while resolving a type in a dependency container.
@ -33,6 +34,10 @@ class ResolveException : Exception {
this(string message, TypeInfo resolveType) {
super(format("Exception while resolving type %s: %s", resolveType.toString(), message));
}
this(Throwable cause, TypeInfo resolveType) {
super(format("Exception while resolving type %s", resolveType.toString()), cause);
}
}
/**
@ -286,7 +291,12 @@ synchronized class DependencyContainer {
}
Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates);
return resolveAutowiredInstance!QualifierType(registration);
try {
return resolveAutowiredInstance!QualifierType(registration);
} catch (ValueInjectionException e) {
throw new ResolveException(e, resolveType);
}
}
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {

View file

@ -11,23 +11,40 @@
*/
module poodinis.valueinjection;
import std.exception;
/**
* Thrown when something goes wrong during value injection.
*/
class ValueInjectionException : Exception {
mixin basicExceptionCtors;
}
/**
* UDA used for marking class members which should be value-injected.
*
* A key must be supplied, which can be in any format depending on how
* a value injector reads it.
*
* When the injector throws a ValueNotAvailableException, the value is
* not injected and will keep its original assignment.
*
* Examples:
* ---
* class MyClass {
* @Value("general.importantNumber")
* private int number;
* private int number = 8;
* }
* ---
*/
struct Value {
/**
* 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.

View file

@ -7,6 +7,8 @@
import poodinis;
import std.exception;
version(unittest) {
struct Thing {
int x;
@ -58,4 +60,13 @@ version(unittest) {
assert(instance.name == "Le Chef");
assert(instance.thing.x == 8899);
}
// Test injection of values throws exception when injector is not there
unittest {
auto container = new shared DependencyContainer();
container.register!MyConfig;
assertThrown!ResolveException(container.resolve!MyConfig);
assertThrown!ValueInjectionException(autowire(container, new MyConfig()));
}
}