mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Merge pull request #28 from huntlabs/develop
Instance initialization improved
This commit is contained in:
commit
7a26dd12e0
|
@ -36,9 +36,17 @@ class Calendar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
class HardwareClock {
|
class HardwareClock {
|
||||||
// Parameterless constructors will halt any further selection of constructors.
|
// Parameterless constructors will halt any further selection of constructors.
|
||||||
this() {}
|
this() {
|
||||||
|
writeln("default constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
this(string name) {
|
||||||
|
writeln(name);
|
||||||
|
}
|
||||||
|
|
||||||
// As a result, this constructor will not be used when HardwareClock is created.
|
// As a result, this constructor will not be used when HardwareClock is created.
|
||||||
this(Calendar calendar) {
|
this(Calendar calendar) {
|
||||||
|
@ -46,7 +54,6 @@ class HardwareClock {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doThings() {
|
public void doThings() {
|
||||||
import std.stdio;
|
|
||||||
writeln("Things are being done!");
|
writeln("Things are being done!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +64,10 @@ void main() {
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!Scheduler;
|
dependencies.register!Scheduler;
|
||||||
dependencies.register!Calendar;
|
dependencies.register!Calendar;
|
||||||
dependencies.register!HardwareClock;
|
dependencies.register!HardwareClock( {
|
||||||
|
writeln("Running the creator");
|
||||||
|
return new HardwareClock("clock name");
|
||||||
|
});
|
||||||
|
|
||||||
auto scheduler = dependencies.resolve!Scheduler;
|
auto scheduler = dependencies.resolve!Scheduler;
|
||||||
scheduler.scheduleJob();
|
scheduler.scheduleJob();
|
||||||
|
|
|
@ -42,8 +42,14 @@ class AClass {
|
||||||
|
|
||||||
public void main() {
|
public void main() {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
container.register!ADependency;
|
container.register!(ADependency).onConstructed((Object obj) {
|
||||||
container.register!AClass;
|
writeln("ADependency constructed");
|
||||||
|
});
|
||||||
|
|
||||||
|
container.register!(AClass).onConstructed((Object obj) {
|
||||||
|
writeln("AClass constructed");
|
||||||
|
});
|
||||||
|
|
||||||
auto instance = container.resolve!AClass; // Will cause the post constructor to be called.
|
auto instance = container.resolve!AClass; // Will cause the post constructor to be called.
|
||||||
container.removeRegistration!AClass; // Will cause the pre destructor to be called.
|
container.removeRegistration!AClass; // Will cause the pre destructor to be called.
|
||||||
|
|
||||||
|
|
|
@ -267,9 +267,10 @@ class AutowiredRegistration(RegistrationType : Object) : Registration {
|
||||||
void delegate() preDestructor = null;
|
void delegate() preDestructor = null;
|
||||||
foreach (memberName; __traits(allMembers, RegistrationType)) {
|
foreach (memberName; __traits(allMembers, RegistrationType)) {
|
||||||
mixin(createImportsString!RegistrationType);
|
mixin(createImportsString!RegistrationType);
|
||||||
|
enum QualifiedName = fullyQualifiedName!RegistrationType ~ `.` ~ memberName;
|
||||||
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
||||||
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
||||||
&& isFunction!(mixin(fullyQualifiedName!RegistrationType ~ `.` ~ memberName))
|
&& isFunction1!(mixin(QualifiedName))
|
||||||
&& hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) {
|
&& hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) {
|
||||||
preDestructor = &__traits(getMember, instance, memberName);
|
preDestructor = &__traits(getMember, instance, memberName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ debug {
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias InjectionInitializer(T) = T delegate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
@ -147,6 +149,11 @@ synchronized class DependencyContainer {
|
||||||
return register!(ConcreteType, ConcreteType)(options);
|
return register!(ConcreteType, ConcreteType)(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Registration register(ConcreteType)(InjectionInitializer!ConcreteType creator,
|
||||||
|
RegistrationOption options = RegistrationOption.none) {
|
||||||
|
return register!(ConcreteType, ConcreteType)(creator, options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency by super type.
|
* Register a dependency by super type.
|
||||||
*
|
*
|
||||||
|
@ -164,7 +171,9 @@ synchronized class DependencyContainer {
|
||||||
*
|
*
|
||||||
* See_Also: singleInstance, newInstance, existingInstance, RegistrationOption
|
* See_Also: singleInstance, newInstance, existingInstance, RegistrationOption
|
||||||
*/
|
*/
|
||||||
public Registration register(SuperType, ConcreteType : SuperType)(RegistrationOption options = RegistrationOption.none) if (!is(ConcreteType == struct)) {
|
public Registration register(SuperType, ConcreteType : SuperType)(
|
||||||
|
RegistrationOption options = RegistrationOption.none) if (!is(ConcreteType == struct)) {
|
||||||
|
|
||||||
TypeInfo registeredType = typeid(SuperType);
|
TypeInfo registeredType = typeid(SuperType);
|
||||||
TypeInfo_Class concreteType = typeid(ConcreteType);
|
TypeInfo_Class concreteType = typeid(ConcreteType);
|
||||||
|
|
||||||
|
@ -192,6 +201,44 @@ synchronized class DependencyContainer {
|
||||||
return newRegistration;
|
return newRegistration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Registration register(SuperType, ConcreteType : SuperType)(InjectionInitializer!ConcreteType creator,
|
||||||
|
RegistrationOption options = RegistrationOption.none) if (!is(ConcreteType == struct)) {
|
||||||
|
|
||||||
|
TypeInfo registeredType = typeid(SuperType);
|
||||||
|
TypeInfo_Class concreteType = typeid(ConcreteType);
|
||||||
|
|
||||||
|
debug(poodinisVerbose) {
|
||||||
|
writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
||||||
|
if (existingRegistration) {
|
||||||
|
return existingRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceFactory instanceFactory = new class InstanceFactory {
|
||||||
|
protected override Object createInstance() {
|
||||||
|
return creator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this);
|
||||||
|
newRegistration.singleInstance();
|
||||||
|
|
||||||
|
static if (!is(SuperType == ConcreteType)) {
|
||||||
|
if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) {
|
||||||
|
auto concreteTypeRegistration = register!ConcreteType;
|
||||||
|
concreteTypeRegistration.linkTo(newRegistration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registrations[registeredType] ~= cast(shared(Registration)) newRegistration;
|
||||||
|
return newRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
||||||
return ((options | persistentOptions) & option) != 0;
|
return ((options | persistentOptions) & option) != 0;
|
||||||
}
|
}
|
||||||
|
@ -326,6 +373,12 @@ synchronized class DependencyContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isRegistered(RegistrationType)() {
|
||||||
|
TypeInfo typeInfo = typeid(RegistrationType);
|
||||||
|
auto candidates = typeInfo in registrations;
|
||||||
|
return candidates !is null;
|
||||||
|
}
|
||||||
|
|
||||||
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
|
private QualifierType resolveAutowiredInstance(QualifierType)(Registration registration) {
|
||||||
QualifierType instance;
|
QualifierType instance;
|
||||||
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
|
if (!(cast(Registration[]) autowireStack).canFind(registration)) {
|
||||||
|
@ -393,10 +446,10 @@ synchronized class DependencyContainer {
|
||||||
private void callPostConstructors(Type)(Type instance) {
|
private void callPostConstructors(Type)(Type instance) {
|
||||||
foreach (memberName; __traits(allMembers, Type)) {
|
foreach (memberName; __traits(allMembers, Type)) {
|
||||||
mixin(createImportsString!Type);
|
mixin(createImportsString!Type);
|
||||||
|
enum QualifiedName = fullyQualifiedName!Type ~ `.` ~ memberName;
|
||||||
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName)))
|
||||||
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
&& __traits(getProtection, __traits(getMember, instance, memberName)) == "public"
|
||||||
&& isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName))
|
&& isFunction1!(mixin(QualifiedName))
|
||||||
&& hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) {
|
&& hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) {
|
||||||
__traits(getMember, instance, memberName)();
|
__traits(getMember, instance, memberName)();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import std.stdio;
|
||||||
|
|
||||||
alias CreatesSingleton = Flag!"CreatesSingleton";
|
alias CreatesSingleton = Flag!"CreatesSingleton";
|
||||||
alias InstanceFactoryMethod = Object delegate();
|
alias InstanceFactoryMethod = Object delegate();
|
||||||
|
alias InstanceEventHandler = void delegate(Object instance);
|
||||||
|
|
||||||
class InstanceCreationException : Exception {
|
class InstanceCreationException : Exception {
|
||||||
this(string message, string file = __FILE__, size_t line = __LINE__) {
|
this(string message, string file = __FILE__, size_t line = __LINE__) {
|
||||||
|
@ -39,6 +40,7 @@ struct InstanceFactoryParameters {
|
||||||
class InstanceFactory {
|
class InstanceFactory {
|
||||||
private Object instance = null;
|
private Object instance = null;
|
||||||
private InstanceFactoryParameters _factoryParameters;
|
private InstanceFactoryParameters _factoryParameters;
|
||||||
|
private InstanceEventHandler _constructionHandler;
|
||||||
|
|
||||||
this() {
|
this() {
|
||||||
factoryParameters = InstanceFactoryParameters();
|
factoryParameters = InstanceFactoryParameters();
|
||||||
|
@ -75,9 +77,17 @@ class InstanceFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
instance = _factoryParameters.factoryMethod();
|
instance = _factoryParameters.factoryMethod();
|
||||||
|
if(_constructionHandler !is null) {
|
||||||
|
_constructionHandler(instance);
|
||||||
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onConstructed(InstanceEventHandler handler) {
|
||||||
|
_constructionHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
private void printDebugUseExistingInstance() {
|
private void printDebugUseExistingInstance() {
|
||||||
if (_factoryParameters.instanceType !is null) {
|
if (_factoryParameters.instanceType !is null) {
|
||||||
writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString()));
|
writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString()));
|
||||||
|
|
|
@ -43,21 +43,24 @@ static if (!__traits(compiles, basicExceptionCtors)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (!__traits(compiles, isFunction)) {
|
static if (!__traits(compiles, isFunction1)) {
|
||||||
template isFunction(X...) if (X.length == 1)
|
template isFunction1(X...)
|
||||||
{
|
{
|
||||||
|
static if (X.length > 1) {
|
||||||
|
enum isFunction1 = false;
|
||||||
|
} else
|
||||||
static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
|
static if (is(typeof(&X[0]) U : U*) && is(U == function) ||
|
||||||
is(typeof(&X[0]) U == delegate))
|
is(typeof(&X[0]) U == delegate))
|
||||||
{
|
{
|
||||||
// x is a (nested) function symbol.
|
// x is a (nested) function symbol.
|
||||||
enum isFunction = true;
|
enum isFunction1 = true;
|
||||||
}
|
}
|
||||||
else static if (is(X[0] T))
|
else static if (is(X[0] T))
|
||||||
{
|
{
|
||||||
// x is a type. Take the type of it and examine.
|
// x is a type. Take the type of it and examine.
|
||||||
enum isFunction = is(T == function);
|
enum isFunction1 = is(T == function);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
enum isFunction = false;
|
enum isFunction1 = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ class Registration {
|
||||||
return linkedRegistration.getInstance(context);
|
return linkedRegistration.getInstance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (instanceFactory is null) {
|
if (instanceFactory is null) {
|
||||||
throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString());
|
throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString());
|
||||||
}
|
}
|
||||||
|
@ -72,6 +71,12 @@ class Registration {
|
||||||
this.linkedRegistration = registration;
|
this.linkedRegistration = registration;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Registration onConstructed(InstanceEventHandler handler) {
|
||||||
|
if(instanceFactory !is null)
|
||||||
|
instanceFactory.onConstructed(handler);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue