From 7ba8e545f6edf4c10ae07a56e3878ed00b2ab2ac Mon Sep 17 00:00:00 2001 From: Mike Bierlee Date: Wed, 14 Dec 2016 21:49:56 +0100 Subject: [PATCH] Move context registration related method out of container Should be still usable as before because of UFCS --- source/poodinis/container.d | 15 ----- source/poodinis/context.d | 16 +++++ test/poodinis/containertest.d | 111 --------------------------------- test/poodinis/contexttest.d | 112 ++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+), 126 deletions(-) diff --git a/source/poodinis/container.d b/source/poodinis/container.d index e5ae3d2..fb66ba5 100644 --- a/source/poodinis/container.d +++ b/source/poodinis/container.d @@ -384,21 +384,6 @@ synchronized class DependencyContainer { registrations.remove(typeid(RegistrationType)); } - /** - * Register dependencies through an application context. - * - * An application context allows you to fine-tune dependency set-up and instantiation. - * It is mostly used for dependencies which come from an external library or when you don't - * want to use annotations to set-up dependencies in your classes. - */ - public void registerContext(Context : ApplicationContext)() { - auto context = new Context(); - context.registerDependencies(this); - context.registerContextComponents(this); - this.register!(ApplicationContext, Context)().existingInstance(context); - autowire(this, context); - } - /** * Returns a global singleton instance of a dependency container. * Deprecated: create new instance with new keyword or implement your own singleton factory (method) diff --git a/source/poodinis/context.d b/source/poodinis/context.d index 83b1729..5ccfb0c 100644 --- a/source/poodinis/context.d +++ b/source/poodinis/context.d @@ -17,6 +17,7 @@ import poodinis.container; import poodinis.registration; import poodinis.factory; import poodinis.polyfill; +import poodinis.autowire; import std.traits; @@ -44,6 +45,21 @@ struct RegisterByType(Type) { */ struct Prototype {} +/** +* Register dependencies through an application context. +* +* An application context allows you to fine-tune dependency set-up and instantiation. +* It is mostly used for dependencies which come from an external library or when you don't +* want to use annotations to set-up dependencies in your classes. +*/ +public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) { + auto context = new Context(); + context.registerDependencies(container); + context.registerContextComponents(container); + container.register!(ApplicationContext, Context)().existingInstance(context); + autowire(container, context); +} + public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) { foreach (member ; __traits(allMembers, ApplicationContextType)) { static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) { diff --git a/test/poodinis/containertest.d b/test/poodinis/containertest.d index f9147b9..fadc300 100644 --- a/test/poodinis/containertest.d +++ b/test/poodinis/containertest.d @@ -12,52 +12,6 @@ import std.exception; import core.thread; version(unittest) { - class TestContext : ApplicationContext { - public override void registerDependencies(shared(DependencyContainer) container) { - container.register!TestClass; - } - - @Component - public UnrelatedClass unrelated() { - return new UnrelatedClass(); - } - } - - class AutowiredTestContext : ApplicationContext { - - @Autowire - private UnrelatedClass unrelatedClass; - - @Component - public ClassWrapper wrapper() { - return new ClassWrapper(unrelatedClass); - } - } - - class ComplexAutowiredTestContext : ApplicationContext { - - @Autowire - private UnrelatedClass unrelatedClass; - - @Autowire - protected ClassWrapper classWrapper; - - public override void registerDependencies(shared(DependencyContainer) container) { - container.register!UnrelatedClass; - } - - @Component - public ClassWrapper wrapper() { - return new ClassWrapper(unrelatedClass); - } - - @Component - public ClassWrapperWrapper wrapperWrapper() { - return new ClassWrapperWrapper(classWrapper); - } - - } - interface TestInterface { } @@ -165,22 +119,6 @@ version(unittest) { public Wants wants; } - class ClassWrapper { - public Object someClass; - - this(Object someClass) { - this.someClass = someClass; - } - } - - class ClassWrapperWrapper { - public ClassWrapper wrapper; - - this(ClassWrapper wrapper) { - this.wrapper = wrapper; - } - } - class Cocktail { @Autowire public Moolah moolah; @@ -588,55 +526,6 @@ version(unittest) { assert(instance.unrelated !is null); } - // Test setting up simple dependencies through application context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!TestContext; - auto instance = container.resolve!TestClass; - - assert(instance !is null); - } - - // Test resolving dependency from registered application context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!TestContext; - auto instance = container.resolve!UnrelatedClass; - - assert(instance !is null); - } - - // Test autowiring application context - unittest { - auto container = new shared DependencyContainer(); - container.register!UnrelatedClass; - container.registerContext!AutowiredTestContext; - auto instance = container.resolve!ClassWrapper; - - assert(instance !is null); - assert(instance.someClass !is null); - } - - // Test autowiring application context with dependencies registered in same context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!ComplexAutowiredTestContext; - auto instance = container.resolve!ClassWrapperWrapper; - auto wrapper = container.resolve!ClassWrapper; - auto someClass = container.resolve!UnrelatedClass; - - assert(instance !is null); - assert(instance.wrapper is wrapper); - assert(instance.wrapper.someClass is someClass); - } - - // Test resolving registered context - unittest { - auto container = new shared DependencyContainer(); - container.registerContext!TestContext; - container.resolve!ApplicationContext; - } - // Test set persistent registration options unittest { auto container = new shared DependencyContainer(); diff --git a/test/poodinis/contexttest.d b/test/poodinis/contexttest.d index a65f3c9..b18cb8a 100644 --- a/test/poodinis/contexttest.d +++ b/test/poodinis/contexttest.d @@ -49,6 +49,70 @@ version(unittest) { class PieChart {} + class CakeChart : PieChart {} + + class ClassWrapper { + public Object someClass; + + this(Object someClass) { + this.someClass = someClass; + } + } + + class ClassWrapperWrapper { + public ClassWrapper wrapper; + + this(ClassWrapper wrapper) { + this.wrapper = wrapper; + } + } + + class SimpleContext : ApplicationContext { + public override void registerDependencies(shared(DependencyContainer) container) { + container.register!CakeChart; + } + + @Component + public Apple apple() { + return new Apple(); + } + } + + class ComplexAutowiredTestContext : ApplicationContext { + + @Autowire + private Apple apple; + + @Autowire + protected ClassWrapper classWrapper; + + public override void registerDependencies(shared(DependencyContainer) container) { + container.register!Apple; + } + + @Component + public ClassWrapper wrapper() { + return new ClassWrapper(apple); + } + + @Component + public ClassWrapperWrapper wrapperWrapper() { + return new ClassWrapperWrapper(classWrapper); + } + + } + + class AutowiredTestContext : ApplicationContext { + + @Autowire + private Apple apple; + + @Component + public ClassWrapper wrapper() { + return new ClassWrapper(apple); + } + } + class TestContext : ApplicationContext { @Component @@ -138,4 +202,52 @@ version(unittest) { assert(firstInstance !is secondInstance); } + // Test setting up simple dependencies through application context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!SimpleContext; + auto instance = container.resolve!CakeChart; + + assert(instance !is null); + } + + // Test resolving dependency from registered application context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!SimpleContext; + auto instance = container.resolve!Apple; + + assert(instance !is null); + } + + // Test autowiring application context + unittest { + auto container = new shared DependencyContainer(); + container.register!Apple; + container.registerContext!AutowiredTestContext; + auto instance = container.resolve!ClassWrapper; + + assert(instance !is null); + assert(instance.someClass !is null); + } + + // Test autowiring application context with dependencies registered in same context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!ComplexAutowiredTestContext; + auto instance = container.resolve!ClassWrapperWrapper; + auto wrapper = container.resolve!ClassWrapper; + auto someClass = container.resolve!Apple; + + assert(instance !is null); + assert(instance.wrapper is wrapper); + assert(instance.wrapper.someClass is someClass); + } + + // Test resolving registered context + unittest { + auto container = new shared DependencyContainer(); + container.registerContext!TestContext; + container.resolve!ApplicationContext; + } }