mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Add post construction
This commit is contained in:
parent
7ba8e545f6
commit
fbef764b48
|
@ -3,6 +3,7 @@ Poodinis Changelog
|
||||||
**Version NEXT**
|
**Version NEXT**
|
||||||
* ADD value injection. Members with UDA @Value will be attempted to be injected with a value-type. See tutorial and examples for more info.
|
* ADD value injection. Members with UDA @Value will be attempted to be injected with a value-type. See tutorial and examples for more info.
|
||||||
* ADD Phobos 2.072.1 forwards-compatibility for D/Phobos 2.066.1. This means you can use Poodinis with D/Phobos 2.066.1 compatible compilers such as GDC.
|
* ADD Phobos 2.072.1 forwards-compatibility for D/Phobos 2.066.1. This means you can use Poodinis with D/Phobos 2.066.1 compatible compilers such as GDC.
|
||||||
|
* ADD @PostConstruct UDA for marking methods which should be called after a dependency is resolved and autowired.
|
||||||
* FIX nullpointer exception in instance factory when debugging with poodinisVerbose
|
* FIX nullpointer exception in instance factory when debugging with poodinisVerbose
|
||||||
|
|
||||||
**Version 7.0.1**
|
**Version 7.0.1**
|
||||||
|
|
|
@ -13,19 +13,21 @@
|
||||||
|
|
||||||
module poodinis.container;
|
module poodinis.container;
|
||||||
|
|
||||||
import std.string;
|
|
||||||
import std.algorithm;
|
|
||||||
import std.concurrency;
|
|
||||||
|
|
||||||
debug {
|
|
||||||
import std.stdio;
|
|
||||||
}
|
|
||||||
|
|
||||||
import poodinis.registration;
|
import poodinis.registration;
|
||||||
import poodinis.autowire;
|
import poodinis.autowire;
|
||||||
import poodinis.context;
|
import poodinis.context;
|
||||||
import poodinis.factory;
|
import poodinis.factory;
|
||||||
import poodinis.valueinjection;
|
import poodinis.valueinjection;
|
||||||
|
import poodinis.polyfill;
|
||||||
|
|
||||||
|
import std.string;
|
||||||
|
import std.algorithm;
|
||||||
|
import std.concurrency;
|
||||||
|
import std.traits;
|
||||||
|
|
||||||
|
debug {
|
||||||
|
import std.stdio;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when errors occur while resolving a type in a dependency container.
|
* Exception thrown when errors occur while resolving a type in a dependency container.
|
||||||
|
@ -80,6 +82,15 @@ public enum ResolveOption {
|
||||||
noResolveException = 1 << 1
|
noResolveException = 1 << 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methods marked with this UDA within dependencies are called after that dependency
|
||||||
|
* is constructed by the dependency container.
|
||||||
|
*
|
||||||
|
* Multiple methods can be marked and will all be called after construction. The order in which
|
||||||
|
* methods are called is undetermined. Methods should have the signature void(void).
|
||||||
|
*/
|
||||||
|
struct PostConstruct {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dependency container maintains all dependencies registered with it.
|
* The dependency container maintains all dependencies registered with it.
|
||||||
*
|
*
|
||||||
|
@ -293,7 +304,9 @@ synchronized class DependencyContainer {
|
||||||
Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates);
|
Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return resolveAutowiredInstance!QualifierType(registration);
|
QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration);
|
||||||
|
callPostConstructors(newInstance);
|
||||||
|
return newInstance;
|
||||||
} catch (ValueInjectionException e) {
|
} catch (ValueInjectionException e) {
|
||||||
throw new ResolveException(e, resolveType);
|
throw new ResolveException(e, resolveType);
|
||||||
}
|
}
|
||||||
|
@ -363,6 +376,16 @@ synchronized class DependencyContainer {
|
||||||
return getRegistration(candidates, qualifierType);
|
return getRegistration(candidates, qualifierType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void callPostConstructors(Type)(Type instance) {
|
||||||
|
foreach (memberName; __traits(allMembers, Type)) {
|
||||||
|
static if (__traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
||||||
|
&& isCallable!(__traits(getMember, instance, memberName))
|
||||||
|
&& hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) {
|
||||||
|
__traits(getMember, instance, memberName)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all dependency registrations managed by this container.
|
* Clears all dependency registrations managed by this container.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -162,6 +162,44 @@ version(unittest) {
|
||||||
this(Ola ola) {}
|
this(Ola ola) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PostConstructionDependency {
|
||||||
|
public bool postConstructWasCalled = false;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void callMeMaybe() {
|
||||||
|
postConstructWasCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChildOfPostConstruction : PostConstructionDependency {}
|
||||||
|
|
||||||
|
interface ThereWillBePostConstruction {
|
||||||
|
@PostConstruct
|
||||||
|
void constructIt();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ButThereWontBe : ThereWillBePostConstruction {
|
||||||
|
public bool postConstructWasCalled = false;
|
||||||
|
|
||||||
|
public override void constructIt() {
|
||||||
|
postConstructWasCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PostConstructWithAutowiring {
|
||||||
|
@Autowire
|
||||||
|
private PostConstructionDependency dependency;
|
||||||
|
|
||||||
|
@Value("")
|
||||||
|
private int theNumber = 1;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void doIt() {
|
||||||
|
assert(theNumber == 8783);
|
||||||
|
assert(dependency !is null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test register concrete type
|
// Test register concrete type
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
@ -636,4 +674,46 @@ version(unittest) {
|
||||||
container.register!Hello;
|
container.register!Hello;
|
||||||
container.resolve!Hello;
|
container.resolve!Hello;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test PostConstruct method is called after resolving a dependency
|
||||||
|
unittest {
|
||||||
|
auto container = new shared DependencyContainer();
|
||||||
|
container.register!PostConstructionDependency;
|
||||||
|
|
||||||
|
auto instance = container.resolve!PostConstructionDependency;
|
||||||
|
assert(instance.postConstructWasCalled == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test PostConstruct of base type is called
|
||||||
|
unittest {
|
||||||
|
auto container = new shared DependencyContainer();
|
||||||
|
container.register!ChildOfPostConstruction;
|
||||||
|
|
||||||
|
auto instance = container.resolve!ChildOfPostConstruction;
|
||||||
|
assert(instance.postConstructWasCalled == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test PostConstruct of class implementing interface is not called
|
||||||
|
unittest {
|
||||||
|
auto container = new shared DependencyContainer();
|
||||||
|
container.register!ButThereWontBe;
|
||||||
|
|
||||||
|
auto instance = container.resolve!ButThereWontBe;
|
||||||
|
assert(instance.postConstructWasCalled == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test postconstruction happens after autowiring and value injection
|
||||||
|
unittest {
|
||||||
|
class IntInjector : ValueInjector!int {
|
||||||
|
int get(string key) {
|
||||||
|
return 8783;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto container = new shared DependencyContainer();
|
||||||
|
container.register!(ValueInjector!int, IntInjector);
|
||||||
|
container.register!PostConstructionDependency;
|
||||||
|
container.register!PostConstructWithAutowiring;
|
||||||
|
auto instance = container.resolve!PostConstructWithAutowiring;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue