From cc3c0d5f6d2f904ee87ddec96340c9b7bb2bc442 Mon Sep 17 00:00:00 2001 From: Mike Bierlee Date: Fri, 16 May 2014 01:36:17 +0200 Subject: [PATCH] Add type validity check --- source/poodinis/container.d | 27 +++++++++++++++++++++++++-- test/poodinis/containertest.d | 14 +++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/source/poodinis/container.d b/source/poodinis/container.d index e0b8ed6..613f533 100644 --- a/source/poodinis/container.d +++ b/source/poodinis/container.d @@ -1,5 +1,7 @@ module poodinis.container; +import std.string; + struct Registration { TypeInfo registratedType = null; TypeInfo_Class instantiatableType = null; @@ -9,6 +11,12 @@ struct Registration { } } +class RegistrationException : Exception { + this(string message, TypeInfo registratedType, TypeInfo_Class instantiatableType) { + super(format("Exception while registering type %s to %s: %s", registratedType.toString(), instantiatableType.name, message)); + } +} + class Container { private static Registration[TypeInfo] registrations; @@ -20,12 +28,27 @@ class Container { return register!(ConcreteType, ConcreteType)(); } - public static Registration register(InterfaceType, ConcreteType)() { - Registration newRegistration = { typeid(InterfaceType), typeid(ConcreteType) }; + public static Registration register(InterfaceType, ConcreteType)(bool checkTypeValidity = true) { + TypeInfo registeredType = typeid(InterfaceType); + TypeInfo_Class instantiatableType = typeid(ConcreteType); + + if (checkTypeValidity) { + checkValidity!(InterfaceType)(registeredType, instantiatableType); + } + + Registration newRegistration = { registeredType, instantiatableType }; registrations[newRegistration.registratedType] = newRegistration; return newRegistration; } + private static void checkValidity(InterfaceType)(TypeInfo registeredType, TypeInfo_Class instanceType) { + InterfaceType instanceCanBeCastToInterface = cast(InterfaceType) instanceType.create(); + if (!instanceCanBeCastToInterface) { + string errorMessage = format("%s cannot be cast to %s", instanceType.name, registeredType.toString()); + throw new RegistrationException(errorMessage, registeredType, instanceType); + } + } + public static ClassType resolve(ClassType)() { return cast(ClassType) registrations[typeid(ClassType)].getInstance(); } diff --git a/test/poodinis/containertest.d b/test/poodinis/containertest.d index 59cfbda..00d64b0 100644 --- a/test/poodinis/containertest.d +++ b/test/poodinis/containertest.d @@ -1,6 +1,6 @@ import poodinis.container; -import std.stdio; +import std.exception; version(unittest) { interface TestInterface { @@ -35,9 +35,13 @@ version(unittest) { } unittest { - // Test resolve type registered with unrelated type fails - Container.register!(UnrelatedClass, TestClass)(); - UnrelatedClass actualInstance = Container.resolve!(UnrelatedClass)(); - assert(actualInstance is null, "Resolved type is not null"); + // Test register unrelated types fails + assertThrown!RegistrationException(Container.register!(UnrelatedClass, TestClass)(), "Registering unrelated types does not fail"); } + + unittest { + // Test register unrelated types with disabled check on registration + assertNotThrown!RegistrationException(Container.register!(UnrelatedClass, TestClass)(false), "Registering unrelated types while disabling type validity fails"); + } + } \ No newline at end of file