Add type validity check

This commit is contained in:
Mike Bierlee 2014-05-16 01:36:17 +02:00
parent 535f5df482
commit cc3c0d5f6d
2 changed files with 34 additions and 7 deletions

View file

@ -1,5 +1,7 @@
module poodinis.container; module poodinis.container;
import std.string;
struct Registration { struct Registration {
TypeInfo registratedType = null; TypeInfo registratedType = null;
TypeInfo_Class instantiatableType = 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 { class Container {
private static Registration[TypeInfo] registrations; private static Registration[TypeInfo] registrations;
@ -20,12 +28,27 @@ class Container {
return register!(ConcreteType, ConcreteType)(); return register!(ConcreteType, ConcreteType)();
} }
public static Registration register(InterfaceType, ConcreteType)() { public static Registration register(InterfaceType, ConcreteType)(bool checkTypeValidity = true) {
Registration newRegistration = { typeid(InterfaceType), typeid(ConcreteType) }; TypeInfo registeredType = typeid(InterfaceType);
TypeInfo_Class instantiatableType = typeid(ConcreteType);
if (checkTypeValidity) {
checkValidity!(InterfaceType)(registeredType, instantiatableType);
}
Registration newRegistration = { registeredType, instantiatableType };
registrations[newRegistration.registratedType] = newRegistration; registrations[newRegistration.registratedType] = newRegistration;
return 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)() { public static ClassType resolve(ClassType)() {
return cast(ClassType) registrations[typeid(ClassType)].getInstance(); return cast(ClassType) registrations[typeid(ClassType)].getInstance();
} }

View file

@ -1,6 +1,6 @@
import poodinis.container; import poodinis.container;
import std.stdio; import std.exception;
version(unittest) { version(unittest) {
interface TestInterface { interface TestInterface {
@ -35,9 +35,13 @@ version(unittest) {
} }
unittest { unittest {
// Test resolve type registered with unrelated type fails // Test register unrelated types fails
Container.register!(UnrelatedClass, TestClass)(); assertThrown!RegistrationException(Container.register!(UnrelatedClass, TestClass)(), "Registering unrelated types does not fail");
UnrelatedClass actualInstance = Container.resolve!(UnrelatedClass)();
assert(actualInstance is null, "Resolved type is not null");
} }
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");
}
} }