Add registration class that will autowire instances itself

This commit is contained in:
Mike Bierlee 2015-01-25 15:07:11 +01:00
parent 82ea4369b8
commit 9d931f511b
2 changed files with 64 additions and 36 deletions

View file

@ -10,6 +10,7 @@ module poodinis.autowire;
public import poodinis.container;
import std.typetuple;
import std.exception;
debug {
import std.stdio;
@ -81,3 +82,19 @@ mixin template AutowireConstructor() {
public void globalAutowire(Type)(Type instance) {
DependencyContainer.getInstance().autowire(instance);
}
class AutowiredRegistration(RegistrationType : Object) : Registration {
private DependencyContainer container;
public this(TypeInfo registeredType, DependencyContainer container) {
enforce(!(container is null), "Argument 'container' is null. Autowired registrations need to autowire using a container.");
this.container = container;
super(registeredType, typeid(RegistrationType));
}
public override Object getInstance() {
RegistrationType instance = cast(RegistrationType) super.getInstance();
container.autowire(instance);
return instance;
}
}

View file

@ -11,69 +11,69 @@ import std.exception;
version(unittest) {
class ComponentA {}
class ComponentB {
public @Autowire ComponentA componentA;
public bool componentIsNull() {
return componentA is null;
}
}
interface InterfaceA {}
class ComponentC : InterfaceA {}
class ComponentD {
public @Autowire InterfaceA componentC = null;
public bool componentIsNull() {
return componentC is null;
}
}
class DummyAttribute{};
class ComponentE {
@DummyAttribute
public ComponentC componentC;
}
class ComponentF {
@Autowired
public ComponentA componentA;
mixin AutowireConstructor;
}
class ComponentDeclarationCocktail {
alias noomer = int;
@Autowire
public ComponentA componentA;
public void doesNothing() {
}
~this(){
}
}
class ComponentX : InterfaceA {}
class MonkeyShine {
@Autowire!ComponentX
public InterfaceA component;
}
class BootstrapBootstrap {
@Autowire!ComponentX
public InterfaceA componentX;
@Autowire!ComponentC
public InterfaceA componentC;
}
// Test autowiring concrete type to existing instance
unittest {
auto container = new DependencyContainer();
@ -82,7 +82,7 @@ version(unittest) {
container.autowire!(ComponentB)(componentB);
assert(!componentB.componentIsNull(), "Autowirable dependency failed to autowire");
}
// Test autowiring interface type to existing instance
unittest {
auto container = new DependencyContainer();
@ -91,7 +91,7 @@ version(unittest) {
container.autowire!(ComponentD)(componentD);
assert(!componentD.componentIsNull(), "Autowirable dependency failed to autowire");
}
// Test autowiring will only happen once
unittest {
auto container = new DependencyContainer();
@ -103,14 +103,14 @@ version(unittest) {
auto actualComponent = componentD.componentC;
assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance");
}
// Test autowiring unregistered type
unittest {
auto container = new DependencyContainer();
auto componentD = new ComponentD();
assertThrown!(ResolveException)(container.autowire!(ComponentD)(componentD), "Autowiring unregistered type should throw ResolveException");
}
// Test autowiring member with non-autowire attribute does not autowire
unittest {
auto container = new DependencyContainer();
@ -118,7 +118,7 @@ version(unittest) {
container.autowire!ComponentE(componentE);
assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire");
}
// Test autowire in constructor
unittest {
auto container = DependencyContainer.getInstance();
@ -127,37 +127,37 @@ version(unittest) {
auto autowiredComponentA = componentF.componentA;
container.register!(ComponentF).existingInstance(componentF);
assert(componentF.componentA !is null, "Constructor did not autowire component F");
auto resolvedComponentF = container.resolve!ComponentF;
assert(resolvedComponentF.componentA is autowiredComponentA, "Resolving instance of ComponentF rewired members");
container.clearAllRegistrations();
}
// Test autowire class with alias declaration
unittest {
auto container = new DependencyContainer();
container.register!ComponentA;
auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
container.autowire(componentDeclarationCocktail);
assert(componentDeclarationCocktail.componentA !is null, "Autowiring class with non-assignable declarations failed");
}
// Test autowire class with qualifier
unittest {
auto container = new DependencyContainer();
container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX);
auto componentX = container.resolve!(InterfaceA, ComponentX);
auto monkeyShine = new MonkeyShine();
container.autowire(monkeyShine);
assert(monkeyShine.component is componentX, "Autowiring class with qualifier failed");
}
// Test autowire class with multiple qualifiers
unittest {
auto container = new DependencyContainer();
@ -165,11 +165,22 @@ version(unittest) {
container.register!(InterfaceA, ComponentX);
auto componentC = container.resolve!(InterfaceA, ComponentC);
auto componentX = container.resolve!(InterfaceA, ComponentX);
auto bootstrapBootstrap = new BootstrapBootstrap();
container.autowire(bootstrapBootstrap);
assert(bootstrapBootstrap.componentX is componentX, "Autowiring class with multiple qualifiers failed");
assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed");
}
}
// Test getting instance from autowired registration will autowire instance
unittest {
auto container = new DependencyContainer();
container.register!ComponentA;
auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), container).singleInstance();
auto instance = cast(ComponentB) registration.getInstance();
assert(!instance.componentIsNull());
}
}