mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Prevent creation of circular dependencies in constructors
This commit is contained in:
parent
96f52226b4
commit
95e30477c6
|
@ -137,7 +137,7 @@ Constructor injection has the advantage of not having to import Poodinis through
|
||||||
|
|
||||||
Circular dependencies
|
Circular dependencies
|
||||||
---------------------
|
---------------------
|
||||||
Poodinis can autowire circular dependencies when they are registered with `singleInstance` or `existingInstance` registration scopes. Circular dependencies in registrations with `newInstance` scopes will not be autowired, as this would cause an endless loop.
|
Poodinis can autowire circular dependencies when they are registered with `singleInstance` or `existingInstance` registration scopes. Circular dependencies in registrations with `newInstance` scopes will not be autowired, as this would cause an endless loop. Circular dependencies are only supported when autowiring members through the `@Autowire` UDA; circular dependencies in constructors are not supported and will result in an `InstanceCreationException`.
|
||||||
|
|
||||||
Registering and resolving using qualifiers
|
Registering and resolving using qualifiers
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
|
@ -89,6 +89,7 @@ class InstanceFactory {
|
||||||
|
|
||||||
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
||||||
private shared DependencyContainer container;
|
private shared DependencyContainer container;
|
||||||
|
private bool isBeingInjected = false;
|
||||||
|
|
||||||
this(shared DependencyContainer container) {
|
this(shared DependencyContainer container) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
|
@ -120,15 +121,18 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
||||||
|
|
||||||
protected override Object createInstance() {
|
protected override Object createInstance() {
|
||||||
enforce!InstanceCreationException(container, "A dependency container is not defined. Cannot perform constructor injection without one.");
|
enforce!InstanceCreationException(container, "A dependency container is not defined. Cannot perform constructor injection without one.");
|
||||||
|
enforce!InstanceCreationException(!isBeingInjected, format("%s is already being created and injected; possible circular dependencies in constructors?", InstanceType.stringof));
|
||||||
|
|
||||||
Object instance = null;
|
Object instance = null;
|
||||||
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
||||||
foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) {
|
foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) {
|
||||||
static if (parametersAreValid!(Parameters!ctor)) {
|
static if (parametersAreValid!(Parameters!ctor)) {
|
||||||
|
isBeingInjected = true;
|
||||||
mixin(`
|
mixin(`
|
||||||
import ` ~ moduleName!InstanceType ~ `;
|
import ` ~ moduleName!InstanceType ~ `;
|
||||||
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `);
|
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `);
|
||||||
`);
|
`);
|
||||||
|
isBeingInjected = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,14 @@ version(unittest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Pot {
|
||||||
|
this(Kettle kettle) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Kettle {
|
||||||
|
this(Pot pot) {}
|
||||||
|
}
|
||||||
|
|
||||||
// Test register concrete type
|
// Test register concrete type
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
@ -695,4 +703,13 @@ version(unittest) {
|
||||||
assert(instance !is null);
|
assert(instance !is null);
|
||||||
assert(instance.color is container.resolve!Blue);
|
assert(instance.color is container.resolve!Blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test prevention of circular dependencies during constructor injection
|
||||||
|
unittest {
|
||||||
|
auto container = new shared DependencyContainer();
|
||||||
|
container.register!Pot;
|
||||||
|
container.register!Kettle;
|
||||||
|
|
||||||
|
assertThrown!InstanceCreationException(container.resolve!Pot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue