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
|
||||
---------------------
|
||||
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
|
||||
------------------------------------------
|
||||
|
|
|
@ -89,6 +89,7 @@ class InstanceFactory {
|
|||
|
||||
class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
||||
private shared DependencyContainer container;
|
||||
private bool isBeingInjected = false;
|
||||
|
||||
this(shared DependencyContainer container) {
|
||||
this.container = container;
|
||||
|
@ -120,15 +121,18 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory {
|
|||
|
||||
protected override Object createInstance() {
|
||||
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;
|
||||
static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) {
|
||||
foreach(ctor ; __traits(getOverloads, InstanceType, `__ctor`)) {
|
||||
static if (parametersAreValid!(Parameters!ctor)) {
|
||||
isBeingInjected = true;
|
||||
mixin(`
|
||||
import ` ~ moduleName!InstanceType ~ `;
|
||||
instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `);
|
||||
`);
|
||||
isBeingInjected = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,6 +199,14 @@ version(unittest) {
|
|||
}
|
||||
}
|
||||
|
||||
class Pot {
|
||||
this(Kettle kettle) {}
|
||||
}
|
||||
|
||||
class Kettle {
|
||||
this(Pot pot) {}
|
||||
}
|
||||
|
||||
// Test register concrete type
|
||||
unittest {
|
||||
auto container = new shared DependencyContainer();
|
||||
|
@ -695,4 +703,13 @@ version(unittest) {
|
|||
assert(instance !is null);
|
||||
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