From 1bf1734c5315fe8b06494e02e8942ff34673ae42 Mon Sep 17 00:00:00 2001 From: Mike Bierlee Date: Thu, 24 Dec 2015 18:45:18 +0100 Subject: [PATCH] Add registration of components through factory methods A basic version of Bean factories from the Spring framework --- source/poodinis/context.d | 20 +++++++++++++++++ test/poodinis/contexttest.d | 44 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/source/poodinis/context.d b/source/poodinis/context.d index bd4fb65..1b5aecb 100644 --- a/source/poodinis/context.d +++ b/source/poodinis/context.d @@ -14,7 +14,27 @@ module poodinis.context; import poodinis.container; +import poodinis.registration; + +import std.traits; class ApplicationContext { public void registerDependencies(shared(DependencyContainer) container) {} } + +/** +* A component annotation is used for specifying which factory methods produce components in +* an application context. +*/ +struct Component {} + +public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) { + import std.stdio; + foreach (member ; __traits(allMembers, ApplicationContextType)) { + static if (hasUDA!(__traits(getMember, context, member), Component)) { + auto factoryMethod = &__traits(getMember, context, member); + auto registration = container.register!(ReturnType!factoryMethod); + registration.instanceFactory = new InstanceFactory(registration.instantiatableType, CreatesSingleton.yes, null, factoryMethod); + } + } +} diff --git a/test/poodinis/contexttest.d b/test/poodinis/contexttest.d index fd142d1..850c6bb 100644 --- a/test/poodinis/contexttest.d +++ b/test/poodinis/contexttest.d @@ -5,8 +5,50 @@ * The full terms of the license can be found in the LICENSE file. */ -import poodinis.context; +import poodinis; + +import std.exception; version(unittest) { + class Banana { + public string color; + + this(string color) { + this.color = color; + } + } + + class Apple {} + + class TestContext : ApplicationContext { + + @Component + public Banana banana() { + return new Banana("Yellow"); + } + + public Apple apple() { + return new Apple(); + } + } + + //Test register component registrations from context + unittest { + shared(DependencyContainer) container = new DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); + auto bananaInstance = container.resolve!Banana; + + assert(bananaInstance.color == "Yellow"); + } + + //Test non-annotated methods are not registered + unittest { + shared(DependencyContainer) container = new DependencyContainer(); + auto context = new TestContext(); + context.registerContextComponents(container); + assertThrown!ResolveException(container.resolve!Apple); + } + }