diff --git a/example/constructorinjection/app.d b/example/constructorinjection/app.d index f270262..183a0aa 100644 --- a/example/constructorinjection/app.d +++ b/example/constructorinjection/app.d @@ -36,9 +36,17 @@ class Calendar { } } +import std.stdio; + class HardwareClock { // 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. this(Calendar calendar) { @@ -46,7 +54,6 @@ class HardwareClock { } public void doThings() { - import std.stdio; writeln("Things are being done!"); } } @@ -57,7 +64,10 @@ void main() { auto dependencies = new shared DependencyContainer(); dependencies.register!Scheduler; dependencies.register!Calendar; - dependencies.register!HardwareClock; + dependencies.register!HardwareClock( { + writeln("Running the creator"); + return new HardwareClock("clock name"); + }); auto scheduler = dependencies.resolve!Scheduler; scheduler.scheduleJob(); diff --git a/source/poodinis/container.d b/source/poodinis/container.d index 7a2e42f..73b6a15 100644 --- a/source/poodinis/container.d +++ b/source/poodinis/container.d @@ -30,6 +30,8 @@ debug { import std.stdio; } +alias InjectionInitializer(T) = T delegate(); + /** * 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); } + Registration register(ConcreteType)(InjectionInitializer!ConcreteType creator, + RegistrationOption options = RegistrationOption.none) { + return register!(ConcreteType, ConcreteType)(creator, options); + } + /** * Register a dependency by super type. * @@ -164,7 +171,9 @@ synchronized class DependencyContainer { * * 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_Class concreteType = typeid(ConcreteType); @@ -192,6 +201,44 @@ synchronized class DependencyContainer { 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) { return ((options | persistentOptions) & option) != 0; } @@ -391,16 +438,16 @@ synchronized class DependencyContainer { } private void callPostConstructors(Type)(Type instance) { - foreach (memberName; __traits(allMembers, Type)) { - mixin(createImportsString!Type); + // foreach (memberName; __traits(allMembers, Type)) { + // mixin(createImportsString!Type); - static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) - && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" - && isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName)) - && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) { - __traits(getMember, instance, memberName)(); - } - } + // static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) + // && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" + // && isFunction!(mixin(fullyQualifiedName!Type ~ `.` ~ memberName)) + // && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) { + // __traits(getMember, instance, memberName)(); + // } + // } } /**