Add autowiring of dynamic arrays

This commit is contained in:
Mike Bierlee 2015-07-04 14:05:53 +02:00
parent 805a3ebaeb
commit 1ce37e6eda
3 changed files with 46 additions and 14 deletions

View file

@ -3,6 +3,7 @@ Poodinis Changelog
**Next Release** **Next Release**
* ADD canonical package module "package.d". Use "import poodinis;" to import the project. * ADD canonical package module "package.d". Use "import poodinis;" to import the project.
* DEPRECATE module "dependency.d". Please use the canonical package module. See previous point. * DEPRECATE module "dependency.d". Please use the canonical package module. See previous point.
* ADD autowiring of dynamic arrays. All registered instances of the element type of the array will be assigned to it.
**Version 2.1.0** **Version 2.1.0**
* ADD option for registering a class by concrete type when registering that class by supertype. * ADD option for registering a class by concrete type when registering that class by supertype.

View file

@ -22,6 +22,7 @@ public import poodinis.container;
import std.exception; import std.exception;
import std.stdio; import std.stdio;
import std.string; import std.string;
import std.traits;
struct UseMemberType {}; struct UseMemberType {};
@ -92,6 +93,10 @@ private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType, void*
writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, candidateInstanceAddress, instanceType, instanceAddress, member)); writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, candidateInstanceAddress, instanceType, instanceAddress, member));
} }
private void printDebugAutowiringArray(TypeInfo superTypeInfo, TypeInfo instanceType, void* instanceAddress, string member) {
writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", superTypeInfo, instanceType, instanceAddress, member));
}
private void autowireMember(string member, Type)(shared(DependencyContainer) container, Type instance) { private void autowireMember(string member, Type)(shared(DependencyContainer) container, Type instance) {
static if(__traits(compiles, __traits(getMember, instance, member)) && __traits(compiles, __traits(getAttributes, __traits(getMember, instance, member)))) { static if(__traits(compiles, __traits(getMember, instance, member)) && __traits(compiles, __traits(getAttributes, __traits(getMember, instance, member)))) {
foreach(autowireAttribute; __traits(getAttributes, __traits(getMember, instance, member))) { foreach(autowireAttribute; __traits(getAttributes, __traits(getMember, instance, member))) {
@ -99,25 +104,34 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
if (__traits(getMember, instance, member) is null) { if (__traits(getMember, instance, member) is null) {
alias MemberType = typeof(__traits(getMember, instance, member)); alias MemberType = typeof(__traits(getMember, instance, member));
debug(poodinisVerbose) { static if (isDynamicArray!MemberType) {
TypeInfo qualifiedInstanceType = typeid(MemberType); alias ElementType = typeof(__traits(getMember, instance, member)[0]);
} auto instances = container.resolveAll!ElementType;
__traits(getMember, instance, member) = instances;
MemberType qualifiedInstance;
static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) {
alias QualifierType = typeof(autowireAttribute.qualifier);
qualifiedInstance = container.resolve!(MemberType, QualifierType);
debug(poodinisVerbose) { debug(poodinisVerbose) {
qualifiedInstanceType = typeid(QualifierType); printDebugAutowiringArray(typeid(ElementType), typeid(Type), &instance, member);
} }
} else { } else {
qualifiedInstance = container.resolve!(MemberType); debug(poodinisVerbose) {
} TypeInfo qualifiedInstanceType = typeid(MemberType);
}
__traits(getMember, instance, member) = qualifiedInstance; MemberType qualifiedInstance;
static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) {
alias QualifierType = typeof(autowireAttribute.qualifier);
qualifiedInstance = container.resolve!(MemberType, QualifierType);
debug(poodinisVerbose) {
qualifiedInstanceType = typeid(QualifierType);
}
} else {
qualifiedInstance = container.resolve!(MemberType);
}
debug(poodinisVerbose) { __traits(getMember, instance, member) = qualifiedInstance;
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
debug(poodinisVerbose) {
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
}
} }
} }

View file

@ -59,6 +59,11 @@ version(unittest) {
public InterfaceA componentC; public InterfaceA componentC;
} }
class LordOfTheComponents {
@Autowire
public InterfaceA[] components;
}
// Test autowiring concrete type to existing instance // Test autowiring concrete type to existing instance
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); shared(DependencyContainer) container = new DependencyContainer();
@ -153,4 +158,16 @@ version(unittest) {
assert(instance.componentA !is null); assert(instance.componentA !is null);
} }
// Test autowiring a dynamic array with all qualified types
unittest {
shared(DependencyContainer) container = new DependencyContainer();
container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX);
auto lord = new LordOfTheComponents();
container.autowire(lord);
assert(lord.components.length == 2, "Dynamic array was not autowired");
}
} }