mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Add registration class that will autowire instances itself
This commit is contained in:
parent
82ea4369b8
commit
9d931f511b
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue