diff --git a/CHANGES.md b/CHANGES.md index ec9e33f..5462f7b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ Poodinis Changelog **Next Release** * 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. +* ADD autowiring of dynamic arrays. All registered instances of the element type of the array will be assigned to it. **Version 2.1.0** * ADD option for registering a class by concrete type when registering that class by supertype. diff --git a/source/poodinis/autowire.d b/source/poodinis/autowire.d index dea1bac..01aa0f3 100644 --- a/source/poodinis/autowire.d +++ b/source/poodinis/autowire.d @@ -22,6 +22,7 @@ public import poodinis.container; import std.exception; import std.stdio; import std.string; +import std.traits; 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)); } +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) { static if(__traits(compiles, __traits(getMember, instance, member)) && __traits(compiles, __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) { alias MemberType = typeof(__traits(getMember, instance, member)); - debug(poodinisVerbose) { - TypeInfo qualifiedInstanceType = typeid(MemberType); - } - - MemberType qualifiedInstance; - static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) { - alias QualifierType = typeof(autowireAttribute.qualifier); - qualifiedInstance = container.resolve!(MemberType, QualifierType); + static if (isDynamicArray!MemberType) { + alias ElementType = typeof(__traits(getMember, instance, member)[0]); + auto instances = container.resolveAll!ElementType; + __traits(getMember, instance, member) = instances; debug(poodinisVerbose) { - qualifiedInstanceType = typeid(QualifierType); + printDebugAutowiringArray(typeid(ElementType), typeid(Type), &instance, member); } } 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) { - printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member); + __traits(getMember, instance, member) = qualifiedInstance; + + debug(poodinisVerbose) { + printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member); + } } } diff --git a/test/poodinis/autowiretest.d b/test/poodinis/autowiretest.d index f548b03..bc5efae 100644 --- a/test/poodinis/autowiretest.d +++ b/test/poodinis/autowiretest.d @@ -59,6 +59,11 @@ version(unittest) { public InterfaceA componentC; } + class LordOfTheComponents { + @Autowire + public InterfaceA[] components; + } + // Test autowiring concrete type to existing instance unittest { shared(DependencyContainer) container = new DependencyContainer(); @@ -153,4 +158,16 @@ version(unittest) { 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"); + } }