From 3e11ff1e92ce0ee71355ba8e93be01b37edd05f7 Mon Sep 17 00:00:00 2001 From: Mike Bierlee Date: Fri, 3 Jul 2015 23:45:10 +0200 Subject: [PATCH] Add ability to assign new instance to autowired member regardless of registration scope --- source/poodinis/autowire.d | 30 ++++++++++++++++++++++++++++-- test/poodinis/autowiretest.d | 18 ++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/source/poodinis/autowire.d b/source/poodinis/autowire.d index 71b1697..45b2df0 100644 --- a/source/poodinis/autowire.d +++ b/source/poodinis/autowire.d @@ -64,6 +64,21 @@ struct Autowire(QualifierType = UseMemberType) { QualifierType qualifier; }; +/** + * UDA for annotating class members to be autowired with a new instance regardless of their registration scope. + * + * Examples: + *--- + * class Car { + * @Autowire + * @AssignNewInstance + * public Antenna antenna; + * } + *--- + * antenna will always be assigned a new instance of class Antenna. + */ +struct AssignNewInstance {} + private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) { writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress)); } @@ -105,6 +120,8 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con if (__traits(getMember, instance, member) is null) { alias MemberType = typeof(__traits(getMember, instance, member)); + enum assignNewInstance = hasUDA!(__traits(getMember, instance, member), AssignNewInstance); + static if (isDynamicArray!MemberType) { alias MemberElementType = ElementType!MemberType; auto instances = container.resolveAll!MemberElementType; @@ -120,12 +137,12 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con MemberType qualifiedInstance; static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) { alias QualifierType = typeof(autowireAttribute.qualifier); - qualifiedInstance = container.resolve!(MemberType, QualifierType); + qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance)(container); debug(poodinisVerbose) { qualifiedInstanceType = typeid(QualifierType); } } else { - qualifiedInstance = container.resolve!(MemberType); + qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container); } __traits(getMember, instance, member) = qualifiedInstance; @@ -142,6 +159,15 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con } } +private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew)(shared(DependencyContainer) container) { + static if (createNew) { + auto instanceFactory = new NewInstanceScope(typeid(MemberType)); + return cast(MemberType) instanceFactory.getInstance(); + } else { + return container.resolve!(MemberType, QualifierType); + } +} + /** * Autowire the given instance using the globally available dependency container. * diff --git a/test/poodinis/autowiretest.d b/test/poodinis/autowiretest.d index bc5efae..93558bc 100644 --- a/test/poodinis/autowiretest.d +++ b/test/poodinis/autowiretest.d @@ -63,6 +63,11 @@ version(unittest) { @Autowire public InterfaceA[] components; } + class ComponentCharlie { + @Autowire + @AssignNewInstance + public ComponentA componentA; + } // Test autowiring concrete type to existing instance unittest { @@ -170,4 +175,17 @@ version(unittest) { assert(lord.components.length == 2, "Dynamic array was not autowired"); } + + // Test autowiring new instance of singleinstance registration with newInstance UDA + unittest { + shared(DependencyContainer) container = new DependencyContainer(); + container.register!ComponentA; + + auto regularComponentA = container.resolve!ComponentA; + auto charlie = new ComponentCharlie(); + + container.autowire(charlie); + + assert(charlie.componentA !is regularComponentA, "Autowiring class with AssignNewInstance did not yield a different instance"); + } }