diff --git a/example/annotations/app.d b/example/annotations/app.d index f940a8e..1be3520 100644 --- a/example/annotations/app.d +++ b/example/annotations/app.d @@ -12,47 +12,53 @@ import std.digest.md; import std.stdio; import std.conv; -class SecurityAuditor { - public void submitAudit() { +class SecurityAuditor +{ + public void submitAudit() + { writeln("Hmmmyes I have received your audit. It is.... adequate."); } } -class SuperSecurityDevice { +class SuperSecurityDevice +{ private int seed; - public this() { + public this() + { auto randomGenerator = Random(unpredictableSeed); seed = uniform(0, 999, randomGenerator); } - public string getPassword() { + public string getPassword() + { return to!string(seed) ~ "t1m3sp13!!:"; } } -class SecurityManager { - @Autowire - private SuperSecurityDevice levelOneSecurity; +class SecurityManager +{ + @Autowire private SuperSecurityDevice levelOneSecurity; - @Autowire - @AssignNewInstance - private SuperSecurityDevice levelTwoSecurity; + @Autowire @AssignNewInstance private SuperSecurityDevice levelTwoSecurity; - @Autowire - @OptionalDependency - private SecurityAuditor auditor; + @Autowire @OptionalDependency private SecurityAuditor auditor; - public void doAudit() { - if (auditor !is null) { + public void doAudit() + { + if (auditor !is null) + { auditor.submitAudit(); - } else { + } + else + { writeln("I uh, will skip the audit for now..."); } } } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope dependencies.register!SecurityManager; @@ -62,9 +68,12 @@ void main() { writeln("Password for user one: " ~ manager.levelOneSecurity.getPassword()); writeln("Password for user two: " ~ manager.levelTwoSecurity.getPassword()); - if (manager.levelOneSecurity is manager.levelTwoSecurity) { + if (manager.levelOneSecurity is manager.levelTwoSecurity) + { writeln("SECURITY BREACH!!!!!"); // Should not be printed since levelTwoSecurity is a new instance. - } else { + } + else + { writeln("Security okay!"); } diff --git a/example/applicationcontext/app.d b/example/applicationcontext/app.d index 4de5283..4534e85 100644 --- a/example/applicationcontext/app.d +++ b/example/applicationcontext/app.d @@ -9,57 +9,64 @@ import poodinis; import std.stdio; -class TownSquare { +class TownSquare +{ - @Autowire - private MarketStall marketStall; + @Autowire private MarketStall marketStall; - public void makeSound() { + public void makeSound() + { marketStall.announceGoodsForSale(); } - } -interface Goods { +interface Goods +{ public string getGoodsName(); } -class Fish : Goods { - public override string getGoodsName() { +class Fish : Goods +{ + public override string getGoodsName() + { return "Fish"; } } -class MarketStall { +class MarketStall +{ private Goods goods; - this(Goods goods) { + this(Goods goods) + { this.goods = goods; } - public void announceGoodsForSale() { + public void announceGoodsForSale() + { writeln(goods.getGoodsName() ~ " for sale!"); } } -class ExampleApplicationContext : ApplicationContext { +class ExampleApplicationContext : ApplicationContext +{ - @Autowire - private Goods goods; + @Autowire private Goods goods; - public override void registerDependencies(shared(DependencyContainer) container) { + public override void registerDependencies(shared(DependencyContainer) container) + { container.register!(Goods, Fish); container.register!TownSquare; } - @Component - public MarketStall marketStall() { + @Component public MarketStall marketStall() + { return new MarketStall(goods); } - } -void main() { +void main() +{ auto container = new shared DependencyContainer(); container.registerContext!ExampleApplicationContext; diff --git a/example/arraycompletion/app.d b/example/arraycompletion/app.d index dcb9784..93bad5c 100644 --- a/example/arraycompletion/app.d +++ b/example/arraycompletion/app.d @@ -9,40 +9,50 @@ import poodinis; import std.stdio; -interface Pie { +interface Pie +{ public void eat(); } -class BlueBerryPie : Pie { - public override void eat() { +class BlueBerryPie : Pie +{ + public override void eat() + { writeln("Nom nom nom. I like this one!"); } } -class ApplePie : Pie { - public override void eat() { +class ApplePie : Pie +{ + public override void eat() + { writeln("Nom nom nom. These aren't real apples..."); } } -class CardboardBoxPie : Pie { - public override void eat() { +class CardboardBoxPie : Pie +{ + public override void eat() + { writeln("Nom nom nom. This... is not a pie."); } } -class PieEater { - @Autowire - private Pie[] pies; +class PieEater +{ + @Autowire private Pie[] pies; - public void eatThemAll() { - foreach(pie ; pies) { + public void eatThemAll() + { + foreach (pie; pies) + { pie.eat(); } } } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); dependencies.register!(Pie, BlueBerryPie); dependencies.register!(Pie, ApplePie); diff --git a/example/constructorinjection/app.d b/example/constructorinjection/app.d index 0e16c3e..4b62048 100644 --- a/example/constructorinjection/app.d +++ b/example/constructorinjection/app.d @@ -5,54 +5,66 @@ * The full terms of the license can be found in the LICENSE file. */ - import std.stdio; +import std.stdio; -class Scheduler { +class Scheduler +{ private Calendar calendar; // All parameters will autmatically be assigned when Scheduler is created. - this(Calendar calendar) { + this(Calendar calendar) + { this.calendar = calendar; } - public void scheduleJob() { + public void scheduleJob() + { calendar.findOpenDate(); } - } -class Calendar { +class Calendar +{ private HardwareClock hardwareClock; // This constructor contains built-in type "int" and thus will not be used. - this(int initialDateTimeStamp, HardwareClock hardwareClock) { + this(int initialDateTimeStamp, HardwareClock hardwareClock) + { } // This constructor is chosen instead as candidate for injection when Calendar is created. - this(HardwareClock hardwareClock) { + this(HardwareClock hardwareClock) + { this.hardwareClock = hardwareClock; } - public void findOpenDate() { + public void findOpenDate() + { hardwareClock.doThings(); } } -class HardwareClock { +class HardwareClock +{ // Parameterless constructors will halt any further selection of constructors. - this() {} - + this() + { + } + // As a result, this constructor will not be used when HardwareClock is created. - this(Calendar calendar) { + this(Calendar calendar) + { throw new Exception("This constructor should not be used by Poodinis"); } - public void doThings() { + public void doThings() + { writeln("Things are being done!"); } } -void main() { +void main() +{ import poodinis; // Locally imported to emphasize that classes do not depend on Poodinis. auto dependencies = new shared DependencyContainer(); diff --git a/example/postconstructorpredestructor/app.d b/example/postconstructorpredestructor/app.d index b1d8496..2be2abe 100644 --- a/example/postconstructorpredestructor/app.d +++ b/example/postconstructorpredestructor/app.d @@ -9,38 +9,44 @@ import poodinis; import std.stdio; -class ADependency { - @PostConstruct - public void postConstructor() { +class ADependency +{ + @PostConstruct public void postConstructor() + { writeln("The dependency is created."); } - public void callMe() { + public void callMe() + { writeln("The dependency was called."); } } -class AClass { - @Autowire - public ADependency dependency; // Dependencies are autowired before the post-constructor is called. +class AClass +{ + @Autowire public ADependency dependency; // Dependencies are autowired before the post-constructor is called. - @PostConstruct - public void postConstructor() { + @PostConstruct public void postConstructor() + { writeln("The class is created."); - if (dependency !is null) { + if (dependency !is null) + { writeln("The dependency is autowired."); - } else { + } + else + { writeln("The dependency was NOT autowired."); } } - @PreDestroy - public void preDestructor() { + @PreDestroy public void preDestructor() + { writeln("The class is no longer registered with the container."); } } -public void main() { +public void main() +{ auto container = new shared DependencyContainer(); container.register!(ADependency).onConstructed((Object obj) { writeln("ADependency constructed"); diff --git a/example/qualifiers/app.d b/example/qualifiers/app.d index fc178b5..b6c8396 100644 --- a/example/qualifiers/app.d +++ b/example/qualifiers/app.d @@ -9,41 +9,50 @@ import poodinis; import std.stdio; -interface Engine { +interface Engine +{ public void engage(); } -class FuelEngine : Engine { - public void engage() { +class FuelEngine : Engine +{ + public void engage() + { writeln("VROOOOOOM!"); } } -class ElectricEngine : Engine { - public void engage() { +class ElectricEngine : Engine +{ + public void engage() + { writeln("hummmmmmmm...."); } } -class HybridCar { +class HybridCar +{ alias KilometersPerHour = int; - @Autowire!FuelEngine - private Engine fuelEngine; + @Autowire!FuelEngine private Engine fuelEngine; - @Autowire!ElectricEngine - private Engine electricEngine; + @Autowire!ElectricEngine private Engine electricEngine; - public void moveAtSpeed(KilometersPerHour speed) { - if (speed <= 45) { + public void moveAtSpeed(KilometersPerHour speed) + { + if (speed <= 45) + { electricEngine.engage(); - } else { + } + else + { fuelEngine.engage(); } } } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); dependencies.register!HybridCar; diff --git a/example/quickstart/app.d b/example/quickstart/app.d index e4236f8..44ebf15 100644 --- a/example/quickstart/app.d +++ b/example/quickstart/app.d @@ -7,24 +7,31 @@ import poodinis; -class Driver {} +class Driver +{ +} -interface Database {}; +interface Database +{ +} -class RelationalDatabase : Database { +class RelationalDatabase : Database +{ private Driver driver; - this(Driver driver) { // Automatically injected on creation by container + this(Driver driver) + { // Automatically injected on creation by container this.driver = driver; } } -class DataWriter { - @Autowire - private Database database; // Automatically injected when class is resolved +class DataWriter +{ + @Autowire private Database database; // Automatically injected when class is resolved } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); dependencies.register!Driver; dependencies.register!DataWriter; diff --git a/example/registeronresolve/app.d b/example/registeronresolve/app.d index 0ba6753..7356539 100644 --- a/example/registeronresolve/app.d +++ b/example/registeronresolve/app.d @@ -7,25 +7,28 @@ import poodinis; -class Violin { +class Violin +{ } -interface InstrumentPlayer { +interface InstrumentPlayer +{ } -class ViolinPlayer : InstrumentPlayer { +class ViolinPlayer : InstrumentPlayer +{ // Autowired concrete types can be registered on resolve - @Autowire - private Violin violin; + @Autowire private Violin violin; } -class Orchestra { +class Orchestra +{ // Autowired non-concrete types can be registered on resolved, given they have a qualifier. - @Autowire!ViolinPlayer - private InstrumentPlayer violinPlayer; + @Autowire!ViolinPlayer private InstrumentPlayer violinPlayer; } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); /* diff --git a/example/valueinjection/app.d b/example/valueinjection/app.d index a60f768..5f8134f 100644 --- a/example/valueinjection/app.d +++ b/example/valueinjection/app.d @@ -10,31 +10,38 @@ import poodinis; import std.stdio; import std.string; -class IntValueInjector : ValueInjector!int { - int get(string key) { - switch(key) { - case "http.port": - return 8080; - case "http.keep_alive": - return 60; - default: - throw new ValueNotAvailableException(key); +class IntValueInjector : ValueInjector!int +{ + int get(string key) + { + switch (key) + { + case "http.port": + return 8080; + case "http.keep_alive": + return 60; + default: + throw new ValueNotAvailableException(key); } } } -class StringValueInjector : ValueInjector!string { - string get(string key) { - switch(key) { - case "http.hostname": - return "acme.org"; - default: - throw new ValueNotAvailableException(key); +class StringValueInjector : ValueInjector!string +{ + string get(string key) + { + switch (key) + { + case "http.hostname": + return "acme.org"; + default: + throw new ValueNotAvailableException(key); } } } -class HttpServer { +class HttpServer +{ @Value("http.port") private int port = 80; @@ -48,12 +55,15 @@ class HttpServer { @MandatoryValue("http.keep_alive") private int keepAliveTime; // A ResolveException is thrown when the value is not available, default assignments are not used. - public void serve() { - writeln(format("Serving pages for %s:%s with max connection count of %s", hostName, port, maxConnections)); + public void serve() + { + writeln(format("Serving pages for %s:%s with max connection count of %s", + hostName, port, maxConnections)); } } -void main() { +void main() +{ auto dependencies = new shared DependencyContainer(); dependencies.register!(ValueInjector!int, IntValueInjector); dependencies.register!(ValueInjector!string, StringValueInjector); diff --git a/source/poodinis/autowire.d b/source/poodinis/autowire.d index 0a1fd11..57adcd3 100644 --- a/source/poodinis/autowire.d +++ b/source/poodinis/autowire.d @@ -20,7 +20,8 @@ module poodinis.autowire; import poodinis.container : DependencyContainer, PreDestroy, ResolveException, ResolveOption; import poodinis.registration : Registration, InstantiationContext; import poodinis.factory : InstanceFactory, InstanceFactoryParameters, CreatesSingleton; -import poodinis.valueinjection : ValueInjector, ValueInjectionException, ValueNotAvailableException, Value, MandatoryValue; +import poodinis.valueinjection : ValueInjector, ValueInjectionException, + ValueNotAvailableException, Value, MandatoryValue; import poodinis.altphobos : isFunction; import poodinis.imports : createImportsString; @@ -29,11 +30,14 @@ import std.string : format; import std.traits : BaseClassesTuple, FieldNameTuple, fullyQualifiedName, hasUDA, isDynamicArray; import std.range : ElementType; -debug { +debug +{ import std.stdio : writeln; } -private struct UseMemberType {} +private struct UseMemberType +{ +} /** * UDA for annotating class members as candidates for autowiring. @@ -68,7 +72,8 @@ private struct UseMemberType {} * autowire member "fuelEngine" as if it's of type "FuelEngine". This means that the members of instance "fuelEngine" * will also be autowired because the autowire mechanism knows that member "fuelEngine" is an instance of "FuelEngine" */ -struct Autowire(QualifierType) { +struct Autowire(QualifierType) +{ QualifierType qualifier; } @@ -77,7 +82,9 @@ struct Autowire(QualifierType) { * Optional dependencies will not lead to a resolveException when there is no type registered for them. * The member will remain null. */ -struct OptionalDependency {} +struct OptionalDependency +{ +} /** * UDA for annotating class members to be autowired with a new instance regardless of their registration scope. @@ -92,10 +99,14 @@ struct OptionalDependency {} *--- * antenna will always be assigned a new instance of class Antenna. */ -struct AssignNewInstance {} +struct AssignNewInstance +{ +} -private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) { - debug { +private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) +{ + debug + { writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress)); } } @@ -109,135 +120,207 @@ private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAd * * See_Also: Autowire */ -public void autowire(Type)(shared(DependencyContainer) container, Type instance) { - debug(poodinisVerbose) { +public void autowire(Type)(shared(DependencyContainer) container, Type instance) +{ + debug (poodinisVerbose) + { printDebugAutowiredInstance(typeid(Type), &instance); } // Recurse into base class if there are more between Type and Object in the hierarchy - static if(BaseClassesTuple!Type.length > 1) + static if (BaseClassesTuple!Type.length > 1) { autowire!(BaseClassesTuple!Type[0])(container, instance); } - foreach(index, name; FieldNameTuple!Type) { + foreach (index, name; FieldNameTuple!Type) + { autowireMember!(name, index, Type)(container, instance); } } -private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType, void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) { - debug { - writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, candidateInstanceAddress, instanceType, instanceAddress, member)); +private void printDebugAutowiringCandidate(TypeInfo candidateInstanceType, + void* candidateInstanceAddress, TypeInfo instanceType, void* instanceAddress, string member) +{ + debug + { + writeln(format("DEBUG: Autowired instance [%s@%s] to [%s@%s].%s", candidateInstanceType, + candidateInstanceAddress, instanceType, instanceAddress, member)); } } -private void printDebugAutowiringArray(TypeInfo superTypeInfo, TypeInfo instanceType, void* instanceAddress, string member) { - debug { - writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", superTypeInfo, instanceType, instanceAddress, member)); +private void printDebugAutowiringArray(TypeInfo superTypeInfo, + TypeInfo instanceType, void* instanceAddress, string member) +{ + debug + { + writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", + superTypeInfo, instanceType, instanceAddress, member)); } } -private void autowireMember(string member, size_t memberIndex, Type)(shared(DependencyContainer) container, Type instance) { - foreach(attribute; __traits(getAttributes, Type.tupleof[memberIndex])) { - static if (is(attribute == Autowire!T, T)) { +private void autowireMember(string member, size_t memberIndex, Type)( + shared(DependencyContainer) container, Type instance) +{ + foreach (attribute; __traits(getAttributes, Type.tupleof[memberIndex])) + { + static if (is(attribute == Autowire!T, T)) + { injectInstance!(member, memberIndex, typeof(attribute.qualifier))(container, instance); - } else static if (__traits(isSame, attribute, Autowire)) { + } + else static if (__traits(isSame, attribute, Autowire)) + { injectInstance!(member, memberIndex, UseMemberType)(container, instance); - } else static if (is(typeof(attribute) == Value)) { + } + else static if (is(typeof(attribute) == Value)) + { enum key = attribute.key; injectValue!(member, memberIndex, key, false)(container, instance); - } else static if (is(typeof(attribute) == MandatoryValue)) { + } + else static if (is(typeof(attribute) == MandatoryValue)) + { enum key = attribute.key; injectValue!(member, memberIndex, key, true)(container, instance); } } } -private void injectInstance(string member, size_t memberIndex, QualifierType, Type)(shared(DependencyContainer) container, Type instance) { - if (instance.tupleof[memberIndex] is null) { +private void injectInstance(string member, size_t memberIndex, QualifierType, Type)( + shared(DependencyContainer) container, Type instance) +{ + if (instance.tupleof[memberIndex] is null) + { alias MemberType = typeof(Type.tupleof[memberIndex]); enum isOptional = hasUDA!(Type.tupleof[memberIndex], OptionalDependency); - static if (isDynamicArray!MemberType) { - injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, instance); - } else { - injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container, instance); + static if (isDynamicArray!MemberType) + { + injectMultipleInstances!(member, memberIndex, isOptional, MemberType)(container, + instance); + } + else + { + injectSingleInstance!(member, memberIndex, isOptional, MemberType, QualifierType)(container, + instance); } } } -private void injectMultipleInstances(string member, size_t memberIndex, bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance) { +private void injectMultipleInstances(string member, size_t memberIndex, + bool isOptional, MemberType, Type)(shared(DependencyContainer) container, Type instance) +{ alias MemberElementType = ElementType!MemberType; - static if (isOptional) { + static if (isOptional) + { auto instances = container.resolveAll!MemberElementType(ResolveOption.noResolveException); - } else { + } + else + { auto instances = container.resolveAll!MemberElementType; } instance.tupleof[memberIndex] = instances; - debug(poodinisVerbose) { + debug (poodinisVerbose) + { printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member); } } -private void injectSingleInstance(string member, size_t memberIndex, bool isOptional, MemberType, QualifierType, Type)(shared(DependencyContainer) container, Type instance) { - debug(poodinisVerbose) { +private void injectSingleInstance(string member, size_t memberIndex, + bool isOptional, MemberType, QualifierType, Type)( + shared(DependencyContainer) container, Type instance) +{ + debug (poodinisVerbose) + { TypeInfo qualifiedInstanceType = typeid(MemberType); } enum assignNewInstance = hasUDA!(Type.tupleof[memberIndex], AssignNewInstance); MemberType qualifiedInstance; - static if (!is(QualifierType == UseMemberType)) { - qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance, isOptional)(container); - debug(poodinisVerbose) { + static if (!is(QualifierType == UseMemberType)) + { + qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, + assignNewInstance, isOptional)(container); + debug (poodinisVerbose) + { qualifiedInstanceType = typeid(QualifierType); } - } else { - qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance, isOptional)(container); + } + else + { + qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, + assignNewInstance, isOptional)(container); } instance.tupleof[memberIndex] = qualifiedInstance; - debug(poodinisVerbose) { - printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member); + debug (poodinisVerbose) + { + printDebugAutowiringCandidate(qualifiedInstanceType, + &qualifiedInstance, typeid(Type), &instance, member); } } -private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew, bool isOptional)(shared(DependencyContainer) container) { - static if (createNew) { +private QualifierType createOrResolveInstance(MemberType, QualifierType, + bool createNew, bool isOptional)(shared(DependencyContainer) container) +{ + static if (createNew) + { auto instanceFactory = new InstanceFactory(); - instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), CreatesSingleton.no); + instanceFactory.factoryParameters = InstanceFactoryParameters(typeid(MemberType), + CreatesSingleton.no); return cast(MemberType) instanceFactory.getInstance(); - } else { - static if (isOptional) { + } + else + { + static if (isOptional) + { return container.resolve!(MemberType, QualifierType)(ResolveOption.noResolveException); - } else { + } + else + { return container.resolve!(MemberType, QualifierType); } } } -private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)(shared(DependencyContainer) container, Type instance) { +private void injectValue(string member, size_t memberIndex, string key, bool mandatory, Type)( + shared(DependencyContainer) container, Type instance) +{ alias MemberType = typeof(Type.tupleof[memberIndex]); - try { + try + { auto injector = container.resolve!(ValueInjector!MemberType); instance.tupleof[memberIndex] = injector.get(key); - debug(poodinisVerbose) { + debug (poodinisVerbose) + { printDebugValueInjection(typeid(Type), &instance, member, typeid(MemberType), key); } - } catch (ResolveException e) { - throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s: value injector is missing for this type.", typeid(MemberType), typeid(Type), member)); - } catch (ValueNotAvailableException e) { - static if (mandatory) { - throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s", typeid(MemberType), typeid(Type), member), e); + } + catch (ResolveException e) + { + throw new ValueInjectionException(format( + "Could not inject value of type %s into %s.%s: value injector is missing for this type.", + typeid(MemberType), typeid(Type), member)); + } + catch (ValueNotAvailableException e) + { + static if (mandatory) + { + throw new ValueInjectionException(format("Could not inject value of type %s into %s.%s", + typeid(MemberType), typeid(Type), member), e); } } } -private void printDebugValueInjection(TypeInfo instanceType, void* instanceAddress, string member, TypeInfo valueType, string key) { - debug { - writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s", key, valueType, instanceType, instanceAddress, member)); +private void printDebugValueInjection(TypeInfo instanceType, + void* instanceAddress, string member, TypeInfo valueType, string key) +{ + debug + { + writeln(format("DEBUG: Injected value with key '%s' of type %s into [%s@%s].%s", + key, valueType, instanceType, instanceAddress, member)); } } @@ -247,25 +330,33 @@ private void printDebugValueInjection(TypeInfo instanceType, void* instanceAddre * See_Also: DependencyContainer * Deprecated: Using the global container is undesired. See DependencyContainer.getInstance(). */ -public deprecated void globalAutowire(Type)(Type instance) { +public deprecated void globalAutowire(Type)(Type instance) +{ DependencyContainer.getInstance().autowire(instance); } -class AutowiredRegistration(RegistrationType : Object) : Registration { +class AutowiredRegistration(RegistrationType : Object) : Registration +{ private shared(DependencyContainer) container; - public this(TypeInfo registeredType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { + public this(TypeInfo registeredType, InstanceFactory instanceFactory, + shared(DependencyContainer) originatingContainer) + { super(registeredType, typeid(RegistrationType), instanceFactory, originatingContainer); } - public override Object getInstance(InstantiationContext context = new AutowireInstantiationContext()) { - enforce(!(originatingContainer is null), "The registration's originating container is null. There is no way to resolve autowire dependencies."); + public override Object getInstance( + InstantiationContext context = new AutowireInstantiationContext()) + { + enforce(!(originatingContainer is null), + "The registration's originating container is null. There is no way to resolve autowire dependencies."); RegistrationType instance = cast(RegistrationType) super.getInstance(context); AutowireInstantiationContext autowireContext = cast(AutowireInstantiationContext) context; enforce(!(autowireContext is null), "Given instantiation context type could not be cast to an AutowireInstantiationContext. If you relied on using the default assigned context: make sure you're calling getInstance() on an instance of type AutowiredRegistration!"); - if (autowireContext.autowireInstance) { + if (autowireContext.autowireInstance) + { originatingContainer.autowire(instance); } @@ -274,15 +365,18 @@ class AutowiredRegistration(RegistrationType : Object) : Registration { return instance; } - private void delegate() getPreDestructor(RegistrationType instance) { + private void delegate() getPreDestructor(RegistrationType instance) + { void delegate() preDestructor = null; - foreach (memberName; __traits(allMembers, RegistrationType)) { + foreach (memberName; __traits(allMembers, RegistrationType)) + { mixin(createImportsString!RegistrationType); enum QualifiedName = fullyQualifiedName!RegistrationType ~ `.` ~ memberName; static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) - && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" - && isFunction!(mixin(QualifiedName)) - && hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) { + && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" + && isFunction!(mixin(QualifiedName)) + && hasUDA!(__traits(getMember, instance, memberName), PreDestroy)) + { preDestructor = &__traits(getMember, instance, memberName); } } @@ -291,6 +385,7 @@ class AutowiredRegistration(RegistrationType : Object) : Registration { } } -class AutowireInstantiationContext : InstantiationContext { +class AutowireInstantiationContext : InstantiationContext +{ public bool autowireInstance = true; } diff --git a/source/poodinis/container.d b/source/poodinis/container.d index 36e36f2..debbfba 100644 --- a/source/poodinis/container.d +++ b/source/poodinis/container.d @@ -21,23 +21,27 @@ import poodinis.altphobos : isFunction; import poodinis.imports : createImportsString; import std.string : format; -import std.algorithm: canFind; +import std.algorithm : canFind; import std.traits : fullyQualifiedName, hasUDA, BaseTypeTuple; import std.meta : AliasSeq; -debug { +debug +{ import std.stdio; } /** * Exception thrown when errors occur while resolving a type in a dependency container. */ -class ResolveException : Exception { - this(string message, TypeInfo resolveType) { +class ResolveException : Exception +{ + this(string message, TypeInfo resolveType) + { super(format("Exception while resolving type %s: %s", resolveType.toString(), message)); } - this(Throwable cause, TypeInfo resolveType) { + this(Throwable cause, TypeInfo resolveType) + { super(format("Exception while resolving type %s", resolveType.toString()), cause); } } @@ -45,16 +49,20 @@ class ResolveException : Exception { /** * Exception thrown when errors occur while registering a type in a dependency container. */ -class RegistrationException : Exception { - this(string message, TypeInfo registrationType) { - super(format("Exception while registering type %s: %s", registrationType.toString(), message)); +class RegistrationException : Exception +{ + this(string message, TypeInfo registrationType) + { + super(format("Exception while registering type %s: %s", + registrationType.toString(), message)); } } /** * Options which influence the process of registering dependencies */ -public enum RegistrationOption { +public enum RegistrationOption +{ none = 0, /** * Prevent a concrete type being registered on itself. With this option you will always need @@ -66,7 +74,8 @@ public enum RegistrationOption { /** * Options which influence the process of resolving dependencies */ -public enum ResolveOption { +public enum ResolveOption +{ none = 0, /** * Registers the type you're trying to resolve before returning it. @@ -89,7 +98,9 @@ public enum ResolveOption { * 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 {} +struct PostConstruct +{ +} /** * Methods marked with this UDA within dependencies are called before the container @@ -98,7 +109,9 @@ struct PostConstruct {} * This method is called when removeRegistration or clearAllRegistrations is called. * It will also be called when the container's destructor is called. */ -struct PreDestroy {} +struct PreDestroy +{ +} /** * The dependency container maintains all dependencies registered with it. @@ -110,7 +123,8 @@ struct PreDestroy {} * In most cases you want to use a global singleton dependency container provided by getInstance() to manage all dependencies. * You can still create new instances of this class for exceptional situations. */ -synchronized class DependencyContainer { +synchronized class DependencyContainer +{ private Registration[][TypeInfo] registrations; private Registration[] autowireStack; @@ -118,7 +132,8 @@ synchronized class DependencyContainer { private RegistrationOption persistentRegistrationOptions; private ResolveOption persistentResolveOptions; - ~this() { + ~this() + { clearAllRegistrations(); } @@ -142,7 +157,8 @@ synchronized class DependencyContainer { * * See_Also: singleInstance, newInstance, existingInstance */ - public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) { + public Registration register(ConcreteType)(RegistrationOption options = RegistrationOption.none) + { return register!(ConcreteType, ConcreteType)(options); } @@ -163,27 +179,36 @@ 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); - debug(poodinisVerbose) { - writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString())); + debug (poodinisVerbose) + { + writeln(format("DEBUG: Register type %s (as %s)", + concreteType.toString(), registeredType.toString())); } auto existingRegistration = getExistingRegistration(registeredType, concreteType); - if (existingRegistration) { + if (existingRegistration) + { return existingRegistration; } auto instanceFactory = new ConstructorInjectingInstanceFactory!ConcreteType(this); - auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this); + auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, + instanceFactory, this); newRegistration.singleInstance(); - static if (!is(SuperType == ConcreteType)) { - if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) { + static if (!is(SuperType == ConcreteType)) + { + if (!hasOption(options, persistentRegistrationOptions, + RegistrationOption.doNotAddConcreteTypeRegistration)) + { auto concreteTypeRegistration = register!ConcreteType; concreteTypeRegistration.linkTo(newRegistration); } @@ -193,36 +218,49 @@ synchronized class DependencyContainer { return newRegistration; } - public Registration register(SuperType, ConcreteType)(RegistrationOption options = RegistrationOption.none) - if (!is(SuperType == ConcreteType) && !is(BaseTypeTuple!ConcreteType == AliasSeq!(Object, SuperType)) && !is(BaseTypeTuple!ConcreteType == AliasSeq!(SuperType))) { - pragma(msg, "Cannot register dependency: ", ConcreteType, " is not derived from ", SuperType); + public Registration register(SuperType, ConcreteType)( + RegistrationOption options = RegistrationOption.none) + if (!is(SuperType == ConcreteType) && !is(BaseTypeTuple!ConcreteType == AliasSeq!(Object, + SuperType)) && !is(BaseTypeTuple!ConcreteType == AliasSeq!(SuperType))) + { + pragma(msg, "Cannot register dependency: ", ConcreteType, + " is not derived from ", SuperType); static assert(0, "Cannot register dependency"); } - 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; } - private OptionType buildFlags(OptionType)(OptionType[] options) { + private OptionType buildFlags(OptionType)(OptionType[] options) + { OptionType flags; - foreach (option; options) { + foreach (option; options) + { flags |= option; } return flags; } - private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) { + private Registration getExistingRegistration(TypeInfo registrationType, TypeInfo qualifierType) + { auto existingCandidates = registrationType in registrations; - if (existingCandidates) { - return getRegistration(cast(Registration[]) *existingCandidates, qualifierType); + if (existingCandidates) + { + return getRegistration(cast(Registration[])*existingCandidates, qualifierType); } return null; } - private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) { - foreach(existingRegistration ; candidates) { - if (existingRegistration.instanceType == concreteType) { + private Registration getRegistration(Registration[] candidates, TypeInfo concreteType) + { + foreach (existingRegistration; candidates) + { + if (existingRegistration.instanceType == concreteType) + { return existingRegistration; } } @@ -269,7 +307,10 @@ synchronized class DependencyContainer { * --- * You need to use the resolve method which allows you to specify a qualifier. */ - public RegistrationType resolve(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) if (!is(RegistrationType == struct)) { + public RegistrationType resolve(RegistrationType)( + ResolveOption resolveOptions = ResolveOption.none) + if (!is(RegistrationType == struct)) + { return resolve!(RegistrationType, RegistrationType)(resolveOptions); } @@ -299,53 +340,73 @@ synchronized class DependencyContainer { * container.resolve!(Animal, Dog); * --- */ - public QualifierType resolve(RegistrationType, QualifierType : RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) if (!is(QualifierType == struct)) { + public QualifierType resolve(RegistrationType, QualifierType: + RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) + if (!is(QualifierType == struct)) + { TypeInfo resolveType = typeid(RegistrationType); TypeInfo qualifierType = typeid(QualifierType); - debug(poodinisVerbose) { + debug (poodinisVerbose) + { writeln("DEBUG: Resolving type " ~ resolveType.toString() ~ " with qualifier " ~ qualifierType.toString()); } - static if (__traits(compiles, new QualifierType())) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.registerBeforeResolving)) { + static if (__traits(compiles, new QualifierType())) + { + if (hasOption(resolveOptions, persistentResolveOptions, + ResolveOption.registerBeforeResolving)) + { register!(RegistrationType, QualifierType)(); } } auto candidates = resolveType in registrations; - if (!candidates) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { + if (!candidates) + { + if (hasOption(resolveOptions, persistentResolveOptions, + ResolveOption.noResolveException)) + { return null; } throw new ResolveException("Type not registered.", resolveType); } - Registration registration = getQualifiedRegistration(resolveType, qualifierType, cast(Registration[]) *candidates); + Registration registration = getQualifiedRegistration(resolveType, + qualifierType, cast(Registration[])*candidates); - try { + try + { QualifierType newInstance = resolveAutowiredInstance!QualifierType(registration); callPostConstructors(newInstance); return newInstance; - } catch (ValueInjectionException e) { + } + catch (ValueInjectionException e) + { throw new ResolveException(e, resolveType); } } - bool isRegistered(RegistrationType)() { + 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; - if (!(cast(Registration[]) autowireStack).canFind(registration)) { + if (!(cast(Registration[]) autowireStack).canFind(registration)) + { autowireStack ~= cast(shared(Registration)) registration; - instance = cast(QualifierType) registration.getInstance(new AutowireInstantiationContext()); - autowireStack = autowireStack[0 .. $-1]; - } else { + instance = cast(QualifierType) registration.getInstance( + new AutowireInstantiationContext()); + autowireStack = autowireStack[0 .. $ - 1]; + } + else + { auto autowireContext = new AutowireInstantiationContext(); autowireContext.autowireInstance = false; instance = cast(QualifierType) registration.getInstance(autowireContext); @@ -370,31 +431,43 @@ synchronized class DependencyContainer { * Animal[] animals = container.resolveAll!Animal; * --- */ - public RegistrationType[] resolveAll(RegistrationType)(ResolveOption resolveOptions = ResolveOption.none) { + public RegistrationType[] resolveAll(RegistrationType)( + ResolveOption resolveOptions = ResolveOption.none) + { RegistrationType[] instances; TypeInfo resolveType = typeid(RegistrationType); auto qualifiedRegistrations = resolveType in registrations; - if (!qualifiedRegistrations) { - if (hasOption(resolveOptions, persistentResolveOptions, ResolveOption.noResolveException)) { + if (!qualifiedRegistrations) + { + if (hasOption(resolveOptions, persistentResolveOptions, + ResolveOption.noResolveException)) + { return []; } throw new ResolveException("Type not registered.", resolveType); } - foreach(registration ; cast(Registration[]) *qualifiedRegistrations) { + foreach (registration; cast(Registration[])*qualifiedRegistrations) + { instances ~= resolveAutowiredInstance!RegistrationType(registration); } return instances; } - private Registration getQualifiedRegistration(TypeInfo resolveType, TypeInfo qualifierType, Registration[] candidates) { - if (resolveType == qualifierType) { - if (candidates.length > 1) { + private Registration getQualifiedRegistration(TypeInfo resolveType, + TypeInfo qualifierType, Registration[] candidates) + { + if (resolveType == qualifierType) + { + if (candidates.length > 1) + { string candidateList = candidates.toConcreteTypeListString(); - throw new ResolveException("Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.", resolveType); + throw new ResolveException( + "Multiple qualified candidates available: " ~ candidateList ~ ". Please use a qualifier.", + resolveType); } return candidates[0]; @@ -403,14 +476,17 @@ synchronized class DependencyContainer { return getRegistration(candidates, qualifierType); } - private void callPostConstructors(Type)(Type instance) { - foreach (memberName; __traits(allMembers, Type)) { + private void callPostConstructors(Type)(Type instance) + { + foreach (memberName; __traits(allMembers, Type)) + { mixin(createImportsString!Type); enum QualifiedName = fullyQualifiedName!Type ~ `.` ~ memberName; static if (__traits(compiles, __traits(getProtection, __traits(getMember, instance, memberName))) - && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" - && isFunction!(mixin(QualifiedName)) - && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) { + && __traits(getProtection, __traits(getMember, instance, memberName)) == "public" + && isFunction!(mixin(QualifiedName)) + && hasUDA!(__traits(getMember, instance, memberName), PostConstruct)) + { __traits(getMember, instance, memberName)(); } } @@ -419,8 +495,10 @@ synchronized class DependencyContainer { /** * Clears all dependency registrations managed by this container. */ - public void clearAllRegistrations() { - foreach(registrationsOfType; registrations) { + public void clearAllRegistrations() + { + foreach (registrationsOfType; registrations) + { callPreDestructorsOfRegistrations(registrationsOfType); } registrations.destroy(); @@ -436,16 +514,20 @@ synchronized class DependencyContainer { * container.removeRegistration!Animal; * --- */ - public void removeRegistration(RegistrationType)() { + public void removeRegistration(RegistrationType)() + { auto registrationsOfType = *(typeid(RegistrationType) in registrations); callPreDestructorsOfRegistrations(registrationsOfType); registrations.remove(typeid(RegistrationType)); } - private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) { - foreach(registration; registrations) { + private void callPreDestructorsOfRegistrations(shared(Registration[]) registrations) + { + foreach (registration; registrations) + { Registration unsharedRegistration = cast(Registration) registration; - if (unsharedRegistration.preDestructor !is null) { + if (unsharedRegistration.preDestructor !is null) + { unsharedRegistration.preDestructor()(); } } @@ -454,28 +536,32 @@ synchronized class DependencyContainer { /** * Apply persistent registration options which will be used everytime register() is called. */ - public void setPersistentRegistrationOptions(RegistrationOption options) { + public void setPersistentRegistrationOptions(RegistrationOption options) + { persistentRegistrationOptions = options; } /** * Unsets all applied persistent registration options */ - public void unsetPersistentRegistrationOptions() { + public void unsetPersistentRegistrationOptions() + { persistentRegistrationOptions = RegistrationOption.none; } /** * Apply persistent resolve options which will be used everytime resolve() is called. */ - public void setPersistentResolveOptions(ResolveOption options) { + public void setPersistentResolveOptions(ResolveOption options) + { persistentResolveOptions = options; } /** * Unsets all applied persistent resolve options */ - public void unsetPersistentResolveOptions() { + public void unsetPersistentResolveOptions() + { persistentResolveOptions = ResolveOption.none; } diff --git a/source/poodinis/context.d b/source/poodinis/context.d index a208259..2addc69 100644 --- a/source/poodinis/context.d +++ b/source/poodinis/context.d @@ -20,21 +20,27 @@ import poodinis.autowire : autowire; import std.traits : hasUDA, ReturnType; -class ApplicationContext { - public void registerDependencies(shared(DependencyContainer) container) {} +class ApplicationContext +{ + public void registerDependencies(shared(DependencyContainer) container) + { + } } /** * A component annotation is used for specifying which factory methods produce components in * an application context. */ -struct Component {} +struct Component +{ +} /** * This annotation allows you to specify by which super type the component should be registered. This * enables you to use type-qualified alternatives for dependencies. */ -struct RegisterByType(Type) { +struct RegisterByType(Type) +{ Type type; } @@ -42,7 +48,9 @@ struct RegisterByType(Type) { * Components with the prototype registration will be scoped as dependencies which will create * new instances every time they are resolved. The factory method will be called repeatedly. */ -struct Prototype {} +struct Prototype +{ +} /** * Register dependencies through an application context. @@ -51,7 +59,8 @@ struct Prototype {} * It is mostly used for dependencies which come from an external library or when you don't * want to use annotations to set-up dependencies in your classes. */ -public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) { +public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) +{ auto context = new Context(); context.registerDependencies(container); context.registerContextComponents(container); @@ -59,26 +68,38 @@ public void registerContext(Context : ApplicationContext)(shared(DependencyConta autowire(container, context); } -public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) { - foreach (member ; __traits(allMembers, ApplicationContextType)) { - static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) { +public void registerContextComponents(ApplicationContextType : ApplicationContext)( + ApplicationContextType context, shared(DependencyContainer) container) +{ + foreach (member; __traits(allMembers, ApplicationContextType)) + { + static if (__traits(getProtection, __traits(getMember, context, + member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) + { auto factoryMethod = &__traits(getMember, context, member); Registration registration = null; auto createsSingleton = CreatesSingleton.yes; - foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) { - static if (is(attribute == RegisterByType!T, T)) { - registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod); - } else static if (__traits(isSame, attribute, Prototype)) { + foreach (attribute; __traits(getAttributes, __traits(getMember, context, member))) + { + static if (is(attribute == RegisterByType!T, T)) + { + registration = container.register!(typeof(attribute.type), + ReturnType!factoryMethod); + } + else static if (__traits(isSame, attribute, Prototype)) + { createsSingleton = CreatesSingleton.no; } } - if (registration is null) { + if (registration is null) + { registration = container.register!(ReturnType!factoryMethod); } - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod); + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, createsSingleton, null, factoryMethod); } } } diff --git a/source/poodinis/factory.d b/source/poodinis/factory.d index 972c335..05085c5 100644 --- a/source/poodinis/factory.d +++ b/source/poodinis/factory.d @@ -19,7 +19,8 @@ import std.exception : enforce; import std.traits : Parameters, isBuiltinType, fullyQualifiedName; import std.string : format; -debug { +debug +{ import std.stdio : writeln; } @@ -27,34 +28,42 @@ alias CreatesSingleton = Flag!"CreatesSingleton"; alias InstanceFactoryMethod = Object delegate(); alias InstanceEventHandler = void delegate(Object instance); -class InstanceCreationException : Exception { - this(string message, string file = __FILE__, size_t line = __LINE__) { +class InstanceCreationException : Exception +{ + this(string message, string file = __FILE__, size_t line = __LINE__) + { super(message, file, line); } } -struct InstanceFactoryParameters { +struct InstanceFactoryParameters +{ TypeInfo_Class instanceType; CreatesSingleton createsSingleton = CreatesSingleton.yes; Object existingInstance; InstanceFactoryMethod factoryMethod; } -class InstanceFactory { +class InstanceFactory +{ private Object instance = null; private InstanceFactoryParameters _factoryParameters; private InstanceEventHandler _constructionHandler; - this() { + this() + { factoryParameters = InstanceFactoryParameters(); } - public @property void factoryParameters(InstanceFactoryParameters factoryParameters) { - if (factoryParameters.factoryMethod is null) { + public @property void factoryParameters(InstanceFactoryParameters factoryParameters) + { + if (factoryParameters.factoryMethod is null) + { factoryParameters.factoryMethod = &this.createInstance; } - if (factoryParameters.existingInstance !is null) { + if (factoryParameters.existingInstance !is null) + { factoryParameters.createsSingleton = CreatesSingleton.yes; this.instance = factoryParameters.existingInstance; } @@ -62,73 +71,99 @@ class InstanceFactory { _factoryParameters = factoryParameters; } - public @property InstanceFactoryParameters factoryParameters() { + public @property InstanceFactoryParameters factoryParameters() + { return _factoryParameters; } - public Object getInstance() { - if (_factoryParameters.createsSingleton && instance !is null) { - debug(poodinisVerbose) { + public Object getInstance() + { + if (_factoryParameters.createsSingleton && instance !is null) + { + debug (poodinisVerbose) + { printDebugUseExistingInstance(); } return instance; } - debug(poodinisVerbose) { + debug (poodinisVerbose) + { printDebugCreateNewInstance(); } instance = _factoryParameters.factoryMethod(); - if(_constructionHandler !is null) { + if (_constructionHandler !is null) + { _constructionHandler(instance); } return instance; } - void onConstructed(InstanceEventHandler handler) { + void onConstructed(InstanceEventHandler handler) + { _constructionHandler = handler; } - private void printDebugUseExistingInstance() { - debug { - if (_factoryParameters.instanceType !is null) { - writeln(format("DEBUG: Existing instance returned of type %s", _factoryParameters.instanceType.toString())); - } else { + private void printDebugUseExistingInstance() + { + debug + { + if (_factoryParameters.instanceType !is null) + { + writeln(format("DEBUG: Existing instance returned of type %s", + _factoryParameters.instanceType.toString())); + } + else + { writeln("DEBUG: Existing instance returned from custom factory method"); } } } - private void printDebugCreateNewInstance() { - debug { - if (_factoryParameters.instanceType !is null) { - writeln(format("DEBUG: Creating new instance of type %s", _factoryParameters.instanceType.toString())); - } else { + private void printDebugCreateNewInstance() + { + debug + { + if (_factoryParameters.instanceType !is null) + { + writeln(format("DEBUG: Creating new instance of type %s", + _factoryParameters.instanceType.toString())); + } + else + { writeln("DEBUG: Creating new instance from custom factory method"); } } } - protected Object createInstance() { - enforce!InstanceCreationException(_factoryParameters.instanceType, "Instance type is not defined, cannot create instance without knowing its type."); + protected Object createInstance() + { + enforce!InstanceCreationException(_factoryParameters.instanceType, + "Instance type is not defined, cannot create instance without knowing its type."); return _factoryParameters.instanceType.create(); } } -class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory { +class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory +{ private shared DependencyContainer container; private bool isBeingInjected = false; - this(shared DependencyContainer container) { + this(shared DependencyContainer container) + { this.container = container; } - private static string createArgumentList(Params...)() { + private static string createArgumentList(Params...)() + { string argumentList = ""; - foreach(param; Params) { - if (argumentList.length > 0) { + foreach (param; Params) + { + if (argumentList.length > 0) + { argumentList ~= ","; } @@ -137,18 +172,23 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory { return argumentList; } - private static string createImportList(Params...)() { + private static string createImportList(Params...)() + { string importList = ""; - foreach(param; Params) { + foreach (param; Params) + { importList ~= createImportsString!param; } return importList; } - private static bool parametersAreValid(Params...)() { + private static bool parametersAreValid(Params...)() + { bool isValid = true; - foreach(param; Params) { - if (isBuiltinType!param || is(param == struct)) { + foreach (param; Params) + { + if (isBuiltinType!param || is(param == struct)) + { isValid = false; break; } @@ -157,18 +197,26 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory { return isValid; } - 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)); + 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)) { + static if (__traits(compiles, __traits(getOverloads, InstanceType, `__ctor`))) + { + foreach (ctor; __traits(getOverloads, InstanceType, `__ctor`)) + { + static if (parametersAreValid!(Parameters!ctor)) + { isBeingInjected = true; - mixin(createImportsString!InstanceType - ~ createImportList!(Parameters!ctor) ~ ` - instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!(Parameters!ctor) ~ `); + mixin(createImportsString!InstanceType ~ createImportList!( + Parameters!ctor) ~ ` + instance = new ` ~ fullyQualifiedName!InstanceType ~ `(` ~ createArgumentList!( + Parameters!ctor) ~ `); `); isBeingInjected = false; break; @@ -176,11 +224,14 @@ class ConstructorInjectingInstanceFactory(InstanceType) : InstanceFactory { } } - if (instance is null) { + if (instance is null) + { instance = typeid(InstanceType).create(); } - enforce!InstanceCreationException(instance !is null, "Unable to create instance of type" ~ InstanceType.stringof ~ ", does it have injectable constructors?"); + enforce!InstanceCreationException(instance !is null, + "Unable to create instance of type" ~ InstanceType.stringof + ~ ", does it have injectable constructors?"); return instance; } diff --git a/source/poodinis/imports.d b/source/poodinis/imports.d index 44ff7f2..da3c45d 100644 --- a/source/poodinis/imports.d +++ b/source/poodinis/imports.d @@ -14,15 +14,20 @@ module poodinis.imports; import std.meta : staticIndexOf; import std.traits : moduleName, TemplateArgsOf, isBuiltinType; -public static string createImportsString(Type, ParentTypeList...)() { +public static string createImportsString(Type, ParentTypeList...)() +{ string imports = `import ` ~ moduleName!Type ~ `;`; - static if (__traits(compiles, TemplateArgsOf!Type)) { - foreach(TemplateArgType; TemplateArgsOf!Type) { - static if (!isBuiltinType!TemplateArgType && staticIndexOf!(TemplateArgType, ParentTypeList) == -1) { + static if (__traits(compiles, TemplateArgsOf!Type)) + { + foreach (TemplateArgType; TemplateArgsOf!Type) + { + static if (!isBuiltinType!TemplateArgType + && staticIndexOf!(TemplateArgType, ParentTypeList) == -1) + { imports ~= createImportsString!(TemplateArgType, ParentTypeList, Type); } } } return imports; -} \ No newline at end of file +} diff --git a/source/poodinis/polyfill.d b/source/poodinis/polyfill.d index 7ea5052..325e731 100644 --- a/source/poodinis/polyfill.d +++ b/source/poodinis/polyfill.d @@ -27,7 +27,8 @@ module poodinis.polyfill; import std.exception; -static if (!__traits(compiles, basicExceptionCtors)) { +static if (!__traits(compiles, basicExceptionCtors)) +{ mixin template basicExceptionCtors() { /++ @@ -37,8 +38,7 @@ static if (!__traits(compiles, basicExceptionCtors)) { line = The line number where the exception occurred. next = The previous exception in the chain of exceptions, if any. +/ - this(string msg, string file = __FILE__, size_t line = __LINE__, - Throwable next = null) @nogc @safe pure nothrow + this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @nogc @safe pure nothrow { super(msg, file, line, next); } @@ -50,12 +50,13 @@ static if (!__traits(compiles, basicExceptionCtors)) { file = The file where the exception occurred. line = The line number where the exception occurred. +/ - this(string msg, Throwable next, string file = __FILE__, - size_t line = __LINE__) @nogc @safe pure nothrow + this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @nogc @safe pure nothrow { super(msg, file, line, next); } } -} else { +} +else +{ public import std.exception : basicExceptionCtors; } diff --git a/source/poodinis/registration.d b/source/poodinis/registration.d index 1320ee9..58da0f3 100644 --- a/source/poodinis/registration.d +++ b/source/poodinis/registration.d @@ -14,9 +14,11 @@ module poodinis.registration; import poodinis.container : DependencyContainer; -import poodinis.factory : InstanceFactory, InstanceEventHandler, InstanceCreationException, InstanceFactoryParameters, CreatesSingleton; +import poodinis.factory : InstanceFactory, InstanceEventHandler, + InstanceCreationException, InstanceFactoryParameters, CreatesSingleton; -class Registration { +class Registration +{ private TypeInfo _registeredType = null; private TypeInfo_Class _instanceType = null; private Registration linkedRegistration; @@ -24,56 +26,70 @@ class Registration { private InstanceFactory _instanceFactory; private void delegate() _preDestructor; - public @property registeredType() { + public @property registeredType() + { return _registeredType; } - public @property instanceType() { + public @property instanceType() + { return _instanceType; } - public @property originatingContainer() { + public @property originatingContainer() + { return _originatingContainer; } - public @property instanceFactory() { + public @property instanceFactory() + { return _instanceFactory; } - public @property preDestructor() { + public @property preDestructor() + { return _preDestructor; } - protected @property preDestructor(void delegate() preDestructor) { + protected @property preDestructor(void delegate() preDestructor) + { _preDestructor = preDestructor; } - this(TypeInfo registeredType, TypeInfo_Class instanceType, InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) { + this(TypeInfo registeredType, TypeInfo_Class instanceType, + InstanceFactory instanceFactory, shared(DependencyContainer) originatingContainer) + { this._registeredType = registeredType; this._instanceType = instanceType; this._originatingContainer = originatingContainer; this._instanceFactory = instanceFactory; } - public Object getInstance(InstantiationContext context = new InstantiationContext()) { - if (linkedRegistration !is null) { + public Object getInstance(InstantiationContext context = new InstantiationContext()) + { + if (linkedRegistration !is null) + { return linkedRegistration.getInstance(context); } - if (instanceFactory is null) { - throw new InstanceCreationException("No instance factory defined for registration of type " ~ registeredType.toString()); + if (instanceFactory is null) + { + throw new InstanceCreationException( + "No instance factory defined for registration of type " ~ registeredType.toString()); } return instanceFactory.getInstance(); } - public Registration linkTo(Registration registration) { + public Registration linkTo(Registration registration) + { this.linkedRegistration = registration; return this; } - Registration onConstructed(InstanceEventHandler handler) { - if(instanceFactory !is null) + Registration onConstructed(InstanceEventHandler handler) + { + if (instanceFactory !is null) instanceFactory.onConstructed(handler); return this; } @@ -84,53 +100,66 @@ class Registration { * * Effectively makes the given registration a singleton. */ -public Registration singleInstance(Registration registration) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes); +public Registration singleInstance(Registration registration) +{ + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, CreatesSingleton.yes); return registration; } /** * Scopes registrations to return a new instance every time the given registration is resolved. */ -public Registration newInstance(Registration registration) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no); +public Registration newInstance(Registration registration) +{ + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, CreatesSingleton.no); return registration; } /** * Scopes registrations to return the given instance every time the given registration is resolved. */ -public Registration existingInstance(Registration registration, Object instance) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, instance); +public Registration existingInstance(Registration registration, Object instance) +{ + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, CreatesSingleton.yes, instance); return registration; } /** * Scopes registrations to create new instances using the given initializer delegate. */ -public Registration initializedBy(T : Object)(Registration registration, T delegate() initializer) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.no, null, { - return cast(Object) initializer(); +public Registration initializedBy(T : Object)(Registration registration, T delegate() initializer) +{ + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, CreatesSingleton.no, null, { + return cast(Object) initializer(); }); - + return registration; } /** * Scopes registrations to create a new instance using the given initializer delegate. On subsequent resolves the same instance is returned. */ -public Registration initializedOnceBy(T : Object)(Registration registration, T delegate() initializer) { - registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, CreatesSingleton.yes, null, { - return cast(Object) initializer(); +public Registration initializedOnceBy(T : Object)(Registration registration, T delegate() initializer) +{ + registration.instanceFactory.factoryParameters = InstanceFactoryParameters( + registration.instanceType, CreatesSingleton.yes, null, { + return cast(Object) initializer(); }); - + return registration; } -public string toConcreteTypeListString(Registration[] registrations) { +public string toConcreteTypeListString(Registration[] registrations) +{ auto concreteTypeListString = ""; - foreach (registration ; registrations) { - if (concreteTypeListString.length > 0) { + foreach (registration; registrations) + { + if (concreteTypeListString.length > 0) + { concreteTypeListString ~= ", "; } concreteTypeListString ~= registration.instanceType.toString(); @@ -138,4 +167,6 @@ public string toConcreteTypeListString(Registration[] registrations) { return concreteTypeListString; } -class InstantiationContext {} +class InstantiationContext +{ +} diff --git a/source/poodinis/valueinjection.d b/source/poodinis/valueinjection.d index 7f5340b..1ec2a1e 100644 --- a/source/poodinis/valueinjection.d +++ b/source/poodinis/valueinjection.d @@ -18,19 +18,23 @@ import std.string : format; /** * Thrown when something goes wrong during value injection. */ -class ValueInjectionException : Exception { +class ValueInjectionException : Exception +{ mixin basicExceptionCtors; } /** * Thrown by injectors when the value with the given key cannot be found. */ -class ValueNotAvailableException : Exception { - this(string key) { +class ValueNotAvailableException : Exception +{ + this(string key) + { super(format("Value for key %s is not available", key)); } - this(string key, Throwable cause) { + this(string key, Throwable cause) + { super(format("Value for key %s is not available", key), cause); } } @@ -52,7 +56,8 @@ class ValueNotAvailableException : Exception { * } * --- */ -struct Value { +struct Value +{ /** * The textual key used to find the value by injectors. * @@ -78,7 +83,8 @@ struct Value { * } * --- */ -struct MandatoryValue { +struct MandatoryValue +{ /** * The textual key used to find the value by injectors. * @@ -109,7 +115,8 @@ struct MandatoryValue { * container.register!(ValueInjector!int, MyIntInjector); * --- */ -interface ValueInjector(Type) { +interface ValueInjector(Type) +{ /** * Get a value from the injector by key. * @@ -120,4 +127,3 @@ interface ValueInjector(Type) { */ Type get(string key); } - diff --git a/test/poodinis/autowiretest.d b/test/poodinis/autowiretest.d index 6a0c219..ec2e070 100644 --- a/test/poodinis/autowiretest.d +++ b/test/poodinis/autowiretest.d @@ -10,10 +10,12 @@ import poodinis.test.testClasses; import std.exception; -version(unittest) { +version (unittest) +{ // Test autowiring concrete type to existing instance - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentA; auto componentB = new ComponentB(); @@ -22,7 +24,8 @@ version(unittest) { } // Test autowiring interface type to existing instance - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC); auto componentD = new ComponentD(); @@ -31,16 +34,19 @@ version(unittest) { } // Test autowiring private members - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC); auto componentD = new ComponentD(); container.autowire(componentD); - assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed"); + assert(componentD.privateComponentC is componentD.componentC, + "Autowire private dependency failed"); } // Test autowiring will only happen once - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC).newInstance(); auto componentD = new ComponentD(); @@ -48,37 +54,45 @@ version(unittest) { auto expectedComponent = componentD.componentC; container.autowire(componentD); auto actualComponent = componentD.componentC; - assert(expectedComponent is actualComponent, "Autowiring the second time wired a different instance"); + assert(expectedComponent is actualComponent, + "Autowiring the second time wired a different instance"); } // Test autowiring unregistered type - unittest { + unittest + { auto container = new shared DependencyContainer(); auto componentD = new ComponentD(); - assertThrown!(ResolveException)(container.autowire(componentD), "Autowiring unregistered type should throw ResolveException"); + assertThrown!(ResolveException)(container.autowire(componentD), + "Autowiring unregistered type should throw ResolveException"); } // Test autowiring member with non-autowire attribute does not autowire - unittest { + unittest + { auto container = new shared DependencyContainer(); auto componentE = new ComponentE(); container.autowire(componentE); - assert(componentE.componentC is null, "Autowiring should not occur for members with attributes other than @Autowire"); + assert(componentE.componentC is null, + "Autowiring should not occur for members with attributes other than @Autowire"); } // Test autowire class with alias declaration - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentA; auto componentDeclarationCocktail = new ComponentDeclarationCocktail(); container.autowire(componentDeclarationCocktail); - assert(componentDeclarationCocktail.componentA !is null, "Autowiring class with non-assignable declarations failed"); + assert(componentDeclarationCocktail.componentA !is null, + "Autowiring class with non-assignable declarations failed"); } // Test autowire class with qualifier - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentX); @@ -91,7 +105,8 @@ version(unittest) { } // Test autowire class with multiple qualifiers - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentX); @@ -101,23 +116,29 @@ version(unittest) { auto bootstrapBootstrap = new BootstrapBootstrap(); container.autowire(bootstrapBootstrap); - assert(bootstrapBootstrap.componentX is componentX, "Autowiring class with multiple qualifiers failed"); - assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed"); + assert(bootstrapBootstrap.componentX is componentX, + "Autowiring class with multiple qualifiers failed"); + assert(bootstrapBootstrap.componentC is componentC, + "Autowiring class with multiple qualifiers failed"); } // Test getting instance from autowired registration will autowire instance - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentA; - auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), new InstanceFactory(), container).singleInstance(); - auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext()); + auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), + new InstanceFactory(), container).singleInstance(); + auto instance = cast(ComponentB) registration.getInstance( + new AutowireInstantiationContext()); assert(instance.componentA !is null); } // Test autowiring a dynamic array with all qualified types - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentX); @@ -129,7 +150,8 @@ version(unittest) { } // Test autowiring new instance of singleinstance registration with newInstance UDA - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentA; @@ -138,11 +160,13 @@ version(unittest) { container.autowire(charlie); - assert(charlie.componentA !is regularComponentA, "Autowiring class with AssignNewInstance did not yield a different instance"); + assert(charlie.componentA !is regularComponentA, + "Autowiring class with AssignNewInstance did not yield a different instance"); } // Test autowiring members from base class - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentA; container.register!ComponentB; @@ -155,7 +179,8 @@ version(unittest) { } // Test autowiring optional dependencies - unittest { + unittest + { auto container = new shared DependencyContainer(); auto instance = new OuttaTime(); @@ -167,7 +192,8 @@ version(unittest) { } // Test autowiring class using value injection - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(ValueInjector!int, TestInjector); @@ -181,7 +207,8 @@ version(unittest) { } // Test autowiring classes with recursive template parameters - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!CircularTemplateComponentA; container.register!CircularTemplateComponentB; diff --git a/test/poodinis/containertest.d b/test/poodinis/containertest.d index 5010475..4de75db 100644 --- a/test/poodinis/containertest.d +++ b/test/poodinis/containertest.d @@ -12,17 +12,21 @@ import poodinis.test.foreignDependencies; import std.exception; import core.thread; -version(unittest) { +version (unittest) +{ // Test register concrete type - unittest { + unittest + { auto container = new shared DependencyContainer(); auto registration = container.register!TestClass; - assert(registration.registeredType == typeid(TestClass), "Type of registered type not the same"); + assert(registration.registeredType == typeid(TestClass), + "Type of registered type not the same"); } // Test resolve registered type - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass; TestClass actualInstance = container.resolve!TestClass; @@ -31,110 +35,125 @@ version(unittest) { } // Test register interface - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(TestInterface, TestClass); TestInterface actualInstance = container.resolve!TestInterface; assert(actualInstance !is null, "Resolved type is null"); - assert(cast(TestInterface) actualInstance, "Resolved class is not the same type as expected"); + assert(cast(TestInterface) actualInstance, + "Resolved class is not the same type as expected"); } // Test resolve non-registered type - unittest { + unittest + { auto container = new shared DependencyContainer(); - assertThrown!ResolveException(container.resolve!TestClass, "Resolving non-registered type does not fail"); + assertThrown!ResolveException(container.resolve!TestClass, + "Resolving non-registered type does not fail"); } // Test clear registrations - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass; container.clearAllRegistrations(); - assertThrown!ResolveException(container.resolve!TestClass, "Resolving cleared type does not fail"); + assertThrown!ResolveException(container.resolve!TestClass, + "Resolving cleared type does not fail"); } // Test resolve single instance for type - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass.singleInstance(); auto instance1 = container.resolve!TestClass; auto instance2 = container.resolve!TestClass; - assert(instance1 is instance2, "Resolved instance from single instance scope is not the each time it is resolved"); + assert(instance1 is instance2, + "Resolved instance from single instance scope is not the each time it is resolved"); } // Test resolve new instance for type - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass.newInstance(); auto instance1 = container.resolve!TestClass; auto instance2 = container.resolve!TestClass; - assert(instance1 !is instance2, "Resolved instance from new instance scope is the same each time it is resolved"); + assert(instance1 !is instance2, + "Resolved instance from new instance scope is the same each time it is resolved"); } // Test resolve existing instance for type - unittest { + unittest + { auto container = new shared DependencyContainer(); auto expectedInstance = new TestClass(); container.register!TestClass.existingInstance(expectedInstance); auto actualInstance = container.resolve!TestClass; - assert(expectedInstance is actualInstance, "Resolved instance from existing instance scope is not the same as the registered instance"); + assert(expectedInstance is actualInstance, + "Resolved instance from existing instance scope is not the same as the registered instance"); } // Test creating instance via custom initializer on resolve - unittest { + unittest + { auto container = new shared DependencyContainer(); auto expectedInstance = new TestClass(); - container.register!TestClass.initializedBy({ - return expectedInstance; - }); + container.register!TestClass.initializedBy({ return expectedInstance; }); auto actualInstance = container.resolve!TestClass; - assert(expectedInstance is actualInstance, "Resolved instance does not come from the custom initializer"); + assert(expectedInstance is actualInstance, + "Resolved instance does not come from the custom initializer"); } // Test creating instance via initializedBy creates new instance every time - unittest { + unittest + { auto container = new shared DependencyContainer(); - container.register!TestClass.initializedBy({ - return new TestClass(); - }); + container.register!TestClass.initializedBy({ return new TestClass(); }); auto firstInstance = container.resolve!TestClass; auto secondInstance = container.resolve!TestClass; assert(firstInstance !is secondInstance, "Resolved instance are not different instances"); } // Test creating instance via initializedOnceBy creates a singleton instance - unittest { + unittest + { auto container = new shared DependencyContainer(); - container.register!TestClass.initializedOnceBy({ - return new TestClass(); - }); + container.register!TestClass.initializedOnceBy({ return new TestClass(); }); auto firstInstance = container.resolve!TestClass; auto secondInstance = container.resolve!TestClass; assert(firstInstance is secondInstance, "Resolved instance are different instances"); } // Test autowire resolved instances - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!AutowiredClass; container.register!ComponentClass; auto componentInstance = container.resolve!ComponentClass; auto autowiredInstance = container.resolve!AutowiredClass; - assert(componentInstance.autowiredClass is autowiredInstance, "Member is not autowired upon resolving"); + assert(componentInstance.autowiredClass is autowiredInstance, + "Member is not autowired upon resolving"); } // Test circular autowiring - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ComponentMouse; container.register!ComponentCat; auto mouse = container.resolve!ComponentMouse; auto cat = container.resolve!ComponentCat; - assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat, "Circular dependencies should be autowirable"); + assert(mouse.cat is cat && cat.mouse is mouse && mouse !is cat, + "Circular dependencies should be autowirable"); } // Test remove registration - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass; container.removeRegistration!TestClass; @@ -142,7 +161,8 @@ version(unittest) { } // Test autowiring does not autowire member where instance is non-null - unittest { + unittest + { auto container = new shared DependencyContainer(); auto existingA = new AutowiredClass(); auto existingB = new ComponentClass(); @@ -153,11 +173,13 @@ version(unittest) { auto resolvedA = container.resolve!AutowiredClass; auto resolvedB = container.resolve!ComponentClass; - assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA, "Autowiring shouldn't rewire member when it is already wired to an instance"); + assert(resolvedB.autowiredClass is existingA && resolvedA !is existingA, + "Autowiring shouldn't rewire member when it is already wired to an instance"); } // Test autowiring circular dependency by third-degree - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Eenie; container.register!Meenie; @@ -165,11 +187,13 @@ version(unittest) { auto eenie = container.resolve!Eenie; - assert(eenie.meenie.moe.eenie is eenie, "Autowiring third-degree circular dependency failed"); + assert(eenie.meenie.moe.eenie is eenie, + "Autowiring third-degree circular dependency failed"); } // Test autowiring deep circular dependencies - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Ittie; container.register!Bittie; @@ -181,7 +205,8 @@ version(unittest) { } // Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Ittie.newInstance(); container.register!Bittie.newInstance(); @@ -189,29 +214,37 @@ version(unittest) { auto ittie = container.resolve!Ittie; - assert(ittie.bittie.banana.bittie.banana is null, "Autowiring deep dependencies with newInstance scope autowired a reoccuring type."); + assert(ittie.bittie.banana.bittie.banana is null, + "Autowiring deep dependencies with newInstance scope autowired a reoccuring type."); } // Test autowiring type registered by interface - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Bunena; container.register!Bittie; container.register!(SuperInterface, SuperImplementation); - SuperImplementation superInstance = cast(SuperImplementation) container.resolve!SuperInterface; + SuperImplementation superInstance = cast(SuperImplementation) container + .resolve!SuperInterface; - assert(!(superInstance.banana is null), "Instance which was resolved by interface type was not autowired."); + assert(!(superInstance.banana is null), + "Instance which was resolved by interface type was not autowired."); } // Test reusing a container after clearing all registrations - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Banana; container.clearAllRegistrations(); - try { + try + { container.resolve!Banana; - } catch (ResolveException e) { + } + catch (ResolveException e) + { container.register!Banana; return; } @@ -219,14 +252,16 @@ version(unittest) { } // Test register multiple concrete classess to same interface type - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(Color, Blue); container.register!(Color, Red); } // Test removing all registrations for type with multiple registrations. - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(Color, Blue); container.register!(Color, Red); @@ -234,42 +269,51 @@ version(unittest) { } // Test registering same registration again - unittest { + unittest + { auto container = new shared DependencyContainer(); auto firstRegistration = container.register!(Color, Blue); auto secondRegistration = container.register!(Color, Blue); - assert(firstRegistration is secondRegistration, "First registration is not the same as the second of equal types"); + assert(firstRegistration is secondRegistration, + "First registration is not the same as the second of equal types"); } // Test resolve registration with multiple qualifiers - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(Color, Blue); container.register!(Color, Red); - try { + try + { container.resolve!Color; - } catch (ResolveException e) { + } + catch (ResolveException e) + { return; } assert(false); } // Test resolve registration with multiple qualifiers using a qualifier - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(Color, Blue); container.register!(Color, Red); auto blueInstance = container.resolve!(Color, Blue); auto redInstance = container.resolve!(Color, Red); - assert(blueInstance !is redInstance, "Resolving type with multiple, different registrations yielded the same instance"); + assert(blueInstance !is redInstance, + "Resolving type with multiple, different registrations yielded the same instance"); assert(blueInstance !is null, "Resolved blue instance to null"); assert(redInstance !is null, "Resolved red instance to null"); } // Test autowire of unqualified member typed by interface. - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Spiders; container.register!(TestInterface, TestClass); @@ -280,38 +324,45 @@ version(unittest) { } // Register existing registration - unittest { + unittest + { auto container = new shared DependencyContainer(); auto firstRegistration = container.register!TestClass; auto secondRegistration = container.register!TestClass; - assert(firstRegistration is secondRegistration, "Registering the same registration twice registers the dependencies twice."); + assert(firstRegistration is secondRegistration, + "Registering the same registration twice registers the dependencies twice."); } // Register existing registration by supertype - unittest { + unittest + { auto container = new shared DependencyContainer(); auto firstRegistration = container.register!(TestInterface, TestClass); auto secondRegistration = container.register!(TestInterface, TestClass); - assert(firstRegistration is secondRegistration, "Registering the same registration by super type twice registers the dependencies twice."); + assert(firstRegistration is secondRegistration, + "Registering the same registration by super type twice registers the dependencies twice."); } // Resolve dependency depending on itself - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Recursive; auto instance = container.resolve!Recursive; assert(instance.recursive is instance, "Resolving dependency that depends on itself fails."); - assert(instance.recursive.recursive is instance, "Resolving dependency that depends on itself fails."); + assert(instance.recursive.recursive is instance, + "Resolving dependency that depends on itself fails."); } // Test autowire stack pop-back - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Moolah; container.register!Wants.newInstance(); @@ -324,12 +375,11 @@ version(unittest) { } // Test resolving registration registered in different thread - unittest { + unittest + { auto container = new shared DependencyContainer(); - auto thread = new Thread(delegate() { - container.register!TestClass; - }); + auto thread = new Thread(delegate() { container.register!TestClass; }); thread.start(); thread.join(); @@ -337,41 +387,47 @@ version(unittest) { } // Test resolving instance previously resolved in different thread - unittest { + unittest + { auto container = new shared DependencyContainer(); shared(TestClass) actualTestClass; container.register!TestClass; auto thread = new Thread(delegate() { - actualTestClass = cast(shared(TestClass)) container.resolve!TestClass; + actualTestClass = cast(shared(TestClass)) container.resolve!TestClass; }); thread.start(); thread.join(); shared(TestClass) expectedTestClass = cast(shared(TestClass)) container.resolve!TestClass; - assert(expectedTestClass is actualTestClass, "Instance resolved in main thread is not the one resolved in thread"); + assert(expectedTestClass is actualTestClass, + "Instance resolved in main thread is not the one resolved in thread"); } // Test registering type with option doNotAddConcreteTypeRegistration - unittest { + unittest + { auto container = new shared DependencyContainer(); - container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration); + container.register!(TestInterface, + TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration); auto firstInstance = container.resolve!TestInterface; assertThrown!ResolveException(container.resolve!TestClass); } // Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration); container.resolve!TestClass; } // Test registering type will register by contrete type by default - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(TestInterface, TestClass); @@ -382,7 +438,8 @@ version(unittest) { } // Test resolving all registrations to an interface - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(Color, Blue); container.register!(Color, Red); @@ -393,7 +450,8 @@ version(unittest) { } // Test autowiring instances resolved in array - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!UnrelatedClass; container.register!(TestInterface, TestClassDeux); @@ -405,38 +463,45 @@ version(unittest) { } // Test set persistent registration options - unittest { + unittest + { auto container = new shared DependencyContainer(); - container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); + container.setPersistentRegistrationOptions( + RegistrationOption.doNotAddConcreteTypeRegistration); container.register!(TestInterface, TestClass); assertThrown!ResolveException(container.resolve!TestClass); } // Test unset persistent registration options - unittest { + unittest + { auto container = new shared DependencyContainer(); - container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); + container.setPersistentRegistrationOptions( + RegistrationOption.doNotAddConcreteTypeRegistration); container.unsetPersistentRegistrationOptions(); container.register!(TestInterface, TestClass); container.resolve!TestClass; } // Test registration when resolving - unittest { + unittest + { auto container = new shared DependencyContainer(); container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving); container.resolve!TestClass; } // Test set persistent resolve options - unittest { + unittest + { auto container = new shared DependencyContainer(); container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); container.resolve!TestClass; } // Test unset persistent resolve options - unittest { + unittest + { auto container = new shared DependencyContainer(); container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); container.unsetPersistentResolveOptions(); @@ -444,27 +509,32 @@ version(unittest) { } // Test ResolveOption registerBeforeResolving fails for interfaces - unittest { + unittest + { auto container = new shared DependencyContainer(); - assertThrown!ResolveException(container.resolve!TestInterface(ResolveOption.registerBeforeResolving)); + assertThrown!ResolveException( + container.resolve!TestInterface(ResolveOption.registerBeforeResolving)); } // Test ResolveOption noResolveException does not throw - unittest { + unittest + { auto container = new shared DependencyContainer(); auto instance = container.resolve!TestInterface(ResolveOption.noResolveException); assert(instance is null); } // ResolveOption noResolveException does not throw for resolveAll - unittest { + unittest + { auto container = new shared DependencyContainer(); auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException); assert(instances.length == 0); } // Test autowired, constructor injected class - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Red; container.register!Moolah; @@ -478,7 +548,8 @@ version(unittest) { } // Test injecting constructor with super-type parameter - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Wallpaper; container.register!(Color, Blue); @@ -489,7 +560,8 @@ version(unittest) { } // Test prevention of circular dependencies during constructor injection - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Pot; container.register!Kettle; @@ -498,7 +570,8 @@ version(unittest) { } // Test prevention of transitive circular dependencies during constructor injection - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Rock; container.register!Paper; @@ -508,7 +581,8 @@ version(unittest) { } // Test injection of foreign dependency in constructor - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Ola; container.register!Hello; @@ -516,7 +590,8 @@ version(unittest) { } // Test PostConstruct method is called after resolving a dependency - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!PostConstructionDependency; @@ -525,7 +600,8 @@ version(unittest) { } // Test PostConstruct of base type is called - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ChildOfPostConstruction; @@ -534,7 +610,8 @@ version(unittest) { } // Test PostConstruct of class implementing interface is not called - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ButThereWontBe; @@ -543,7 +620,8 @@ version(unittest) { } // Test postconstruction happens after autowiring and value injection - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(ValueInjector!int, PostConstructingIntInjector); container.register!PostConstructionDependency; @@ -552,7 +630,8 @@ version(unittest) { } // Test PreDestroy is called when removing a registration - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!PreDestroyerOfFates; auto instance = container.resolve!PreDestroyerOfFates; @@ -561,7 +640,8 @@ version(unittest) { } // Test PreDestroy is called when removing all registrations - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!PreDestroyerOfFates; auto instance = container.resolve!PreDestroyerOfFates; @@ -570,7 +650,8 @@ version(unittest) { } // Test PreDestroy is called when the container is destroyed - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!PreDestroyerOfFates; auto instance = container.resolve!PreDestroyerOfFates; diff --git a/test/poodinis/contexttest.d b/test/poodinis/contexttest.d index 8a268c7..479f96c 100644 --- a/test/poodinis/contexttest.d +++ b/test/poodinis/contexttest.d @@ -10,10 +10,12 @@ import poodinis.test.testClasses; import std.exception; -version(unittest) { +version (unittest) +{ //Test register component registrations from context - unittest { + unittest + { auto container = new shared DependencyContainer(); auto context = new TestContext(); context.registerContextComponents(container); @@ -23,7 +25,8 @@ version(unittest) { } //Test non-annotated methods are not registered - unittest { + unittest + { auto container = new shared DependencyContainer(); auto context = new TestContext(); context.registerContextComponents(container); @@ -31,7 +34,8 @@ version(unittest) { } //Test register component by base type - unittest { + unittest + { auto container = new shared DependencyContainer(); auto context = new TestContext(); context.registerContextComponents(container); @@ -40,7 +44,8 @@ version(unittest) { } //Test register components with multiple candidates - unittest { + unittest + { auto container = new shared DependencyContainer(); auto context = new TestContext(); context.registerContextComponents(container); @@ -53,7 +58,8 @@ version(unittest) { } //Test register component as prototype - unittest { + unittest + { auto container = new shared DependencyContainer(); auto context = new TestContext(); context.registerContextComponents(container); @@ -66,7 +72,8 @@ version(unittest) { } // Test setting up simple dependencies through application context - unittest { + unittest + { auto container = new shared DependencyContainer(); container.registerContext!SimpleContext; auto instance = container.resolve!CakeChart; @@ -75,7 +82,8 @@ version(unittest) { } // Test resolving dependency from registered application context - unittest { + unittest + { auto container = new shared DependencyContainer(); container.registerContext!SimpleContext; auto instance = container.resolve!Apple; @@ -84,7 +92,8 @@ version(unittest) { } // Test autowiring application context - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!Apple; container.registerContext!AutowiredTestContext; @@ -95,7 +104,8 @@ version(unittest) { } // Test autowiring application context with dependencies registered in same context - unittest { + unittest + { auto container = new shared DependencyContainer(); container.registerContext!ComplexAutowiredTestContext; auto instance = container.resolve!ClassWrapperWrapper; @@ -108,7 +118,8 @@ version(unittest) { } // Test resolving registered context - unittest { + unittest + { auto container = new shared DependencyContainer(); container.registerContext!TestContext; container.resolve!ApplicationContext; diff --git a/test/poodinis/factorytest.d b/test/poodinis/factorytest.d index fad5a38..f7df502 100644 --- a/test/poodinis/factorytest.d +++ b/test/poodinis/factorytest.d @@ -10,12 +10,15 @@ import poodinis.test.testClasses; import std.exception; -version(unittest) { +version (unittest) +{ // Test instance factory with singletons - unittest { + unittest + { auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), + CreatesSingleton.yes); auto instanceOne = factory.getInstance(); auto instanceTwo = factory.getInstance(); @@ -24,9 +27,11 @@ version(unittest) { } // Test instance factory with new instances - unittest { + unittest + { auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), + CreatesSingleton.no); auto instanceOne = factory.getInstance(); auto instanceTwo = factory.getInstance(); @@ -35,45 +40,57 @@ version(unittest) { } // Test instance factory with existing instances - unittest { + unittest + { auto existingInstance = new TestImplementation(); auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.yes, existingInstance); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), + CreatesSingleton.yes, existingInstance); auto instanceOne = factory.getInstance(); auto instanceTwo = factory.getInstance(); - assert(instanceOne is existingInstance, "Created factory instance is not the existing instance"); - assert(instanceTwo is existingInstance, "Created factory instance is not the existing instance when called again"); + assert(instanceOne is existingInstance, + "Created factory instance is not the existing instance"); + assert(instanceTwo is existingInstance, + "Created factory instance is not the existing instance when called again"); } // Test instance factory with existing instances when setting singleton flag to "no" - unittest { + unittest + { auto existingInstance = new TestImplementation(); auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), CreatesSingleton.no, existingInstance); + factory.factoryParameters = InstanceFactoryParameters(typeid(TestImplementation), + CreatesSingleton.no, existingInstance); auto instance = factory.getInstance(); - assert(instance is existingInstance, "Created factory instance is not the existing instance"); + assert(instance is existingInstance, + "Created factory instance is not the existing instance"); } // Test creating instance using custom factory method - unittest { - Object factoryMethod() { + unittest + { + Object factoryMethod() + { auto instance = new TestImplementation(); instance.someContent = "Ducks!"; return instance; } auto factory = new InstanceFactory(); - factory.factoryParameters = InstanceFactoryParameters(null, CreatesSingleton.yes, null, &factoryMethod); + factory.factoryParameters = InstanceFactoryParameters(null, + CreatesSingleton.yes, null, &factoryMethod); auto instance = cast(TestImplementation) factory.getInstance(); - assert(instance !is null, "No instance was created by factory or could not be cast to expected type"); + assert(instance !is null, + "No instance was created by factory or could not be cast to expected type"); assert(instance.someContent == "Ducks!"); } // Test injecting constructor of class - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!TestImplementation; @@ -85,12 +102,14 @@ version(unittest) { } // Test injecting constructor of class with multiple constructors injects the first candidate - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!SomeOtherClassThen; container.register!TestImplementation; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors(container); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithMultipleConstructors( + container); auto instance = cast(ClassWithMultipleConstructors) factory.getInstance(); assert(instance !is null); @@ -99,12 +118,14 @@ version(unittest) { } // Test injecting constructor of class with multiple constructor parameters - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!SomeOtherClassThen; container.register!TestImplementation; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters(container); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithConstructorWithMultipleParameters( + container); auto instance = cast(ClassWithConstructorWithMultipleParameters) factory.getInstance(); assert(instance !is null); @@ -113,11 +134,13 @@ version(unittest) { } // Test injecting constructor of class with primitive constructor parameters - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!SomeOtherClassThen; - auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor(container); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithPrimitiveConstructor( + container); auto instance = cast(ClassWithPrimitiveConstructor) factory.getInstance(); assert(instance !is null); @@ -125,7 +148,8 @@ version(unittest) { } // Test injecting constructor of class with struct constructor parameters - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!SomeOtherClassThen; @@ -137,7 +161,8 @@ version(unittest) { } // Test injecting constructor of class with empty constructor will skip injection - unittest { + unittest + { auto container = new shared DependencyContainer(); auto factory = new ConstructorInjectingInstanceFactory!ClassWithEmptyConstructor(container); @@ -148,10 +173,12 @@ version(unittest) { } // Test injecting constructor of class with no candidates fails - unittest { + unittest + { auto container = new shared DependencyContainer(); - auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor(container); + auto factory = new ConstructorInjectingInstanceFactory!ClassWithNonInjectableConstructor( + container); assertThrown!InstanceCreationException(factory.getInstance()); } diff --git a/test/poodinis/foreigndependencies.d b/test/poodinis/foreigndependencies.d index c3cd996..abd275f 100644 --- a/test/poodinis/foreigndependencies.d +++ b/test/poodinis/foreigndependencies.d @@ -7,6 +7,9 @@ module poodinis.test.foreignDependencies; -version(unittest) { - class Ola {} +version (unittest) +{ + class Ola + { + } } diff --git a/test/poodinis/registrationtest.d b/test/poodinis/registrationtest.d index 6c13894..bf8f095 100644 --- a/test/poodinis/registrationtest.d +++ b/test/poodinis/registrationtest.d @@ -10,48 +10,65 @@ import poodinis.test.testClasses; import std.exception; -version(unittest) { +version (unittest) +{ // Test getting instance without scope defined throws exception - unittest { + unittest + { Registration registration = new Registration(typeid(TestType), null, null, null); assertThrown!(InstanceCreationException)(registration.getInstance(), null); } // Test set single instance scope using scope setter - unittest { - Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); + unittest + { + Registration registration = new Registration(null, typeid(TestType), + new InstanceFactory(), null); auto chainedRegistration = registration.singleInstance(); auto instance1 = registration.getInstance(); auto instance2 = registration.getInstance(); - assert(instance1 is instance2, "Registration with single instance scope did not return the same instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + assert(instance1 is instance2, + "Registration with single instance scope did not return the same instance"); + assert(registration is chainedRegistration, + "Registration returned by scope setting is not the same as the registration being set"); } // Test set new instance scope using scope setter - unittest { - Registration registration = new Registration(null, typeid(TestType), new InstanceFactory(), null); + unittest + { + Registration registration = new Registration(null, typeid(TestType), + new InstanceFactory(), null); auto chainedRegistration = registration.newInstance(); auto instance1 = registration.getInstance(); auto instance2 = registration.getInstance(); - assert(instance1 !is instance2, "Registration with new instance scope did not return a different instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + assert(instance1 !is instance2, + "Registration with new instance scope did not return a different instance"); + assert(registration is chainedRegistration, + "Registration returned by scope setting is not the same as the registration being set"); } // Test set existing instance scope using scope setter - unittest { + unittest + { Registration registration = new Registration(null, null, new InstanceFactory(), null); auto expectedInstance = new TestType(); auto chainedRegistration = registration.existingInstance(expectedInstance); auto actualInstance = registration.getInstance(); - assert(expectedInstance is expectedInstance, "Registration with existing instance scope did not return the same instance"); - assert(registration is chainedRegistration, "Registration returned by scope setting is not the same as the registration being set"); + assert(expectedInstance is expectedInstance, + "Registration with existing instance scope did not return the same instance"); + assert(registration is chainedRegistration, + "Registration returned by scope setting is not the same as the registration being set"); } // Test linking registrations - unittest { - Registration firstRegistration = new Registration(typeid(TestInterface), typeid(TestImplementation), new InstanceFactory(), null).singleInstance(); - Registration secondRegistration = new Registration(typeid(TestImplementation), typeid(TestImplementation), new InstanceFactory(), null).singleInstance().linkTo(firstRegistration); + unittest + { + Registration firstRegistration = new Registration(typeid(TestInterface), + typeid(TestImplementation), new InstanceFactory(), null).singleInstance(); + Registration secondRegistration = new Registration(typeid(TestImplementation), + typeid(TestImplementation), new InstanceFactory(), null).singleInstance() + .linkTo(firstRegistration); auto firstInstance = firstRegistration.getInstance(); auto secondInstance = secondRegistration.getInstance(); diff --git a/test/poodinis/testclasses.d b/test/poodinis/testclasses.d index 9e71d10..7d1bc3c 100644 --- a/test/poodinis/testclasses.d +++ b/test/poodinis/testclasses.d @@ -10,529 +10,630 @@ module poodinis.test.testClasses; import poodinis; import poodinis.test.foreignDependencies; -version(unittest) { - class ComponentA {} +version (unittest) +{ + class ComponentA + { + } - class ComponentB { + class ComponentB + { public @Autowire ComponentA componentA; } - interface InterfaceA {} + interface InterfaceA + { + } - class ComponentC : InterfaceA {} + class ComponentC : InterfaceA + { + } - class ComponentD { + class ComponentD + { public @Autowire InterfaceA componentC = null; private @Autowire InterfaceA _privateComponentC = null; - public InterfaceA privateComponentC() { + public InterfaceA privateComponentC() + { return _privateComponentC; } } - class DummyAttribute{}; + class DummyAttribute + { + }; - class ComponentE { - @DummyAttribute - public ComponentC componentC; + class ComponentE + { + @DummyAttribute public ComponentC componentC; } - class ComponentDeclarationCocktail { + class ComponentDeclarationCocktail + { alias noomer = int; - @Autowire - public ComponentA componentA; + @Autowire public ComponentA componentA; - public void doesNothing() { + public void doesNothing() + { } - ~this(){ + ~this() + { } } - class ComponentX : InterfaceA {} - - class ComponentZ : ComponentB { + class ComponentX : InterfaceA + { } - class MonkeyShine { - @Autowire!ComponentX - public InterfaceA component; + class ComponentZ : ComponentB + { } - class BootstrapBootstrap { - @Autowire!ComponentX - public InterfaceA componentX; - - @Autowire!ComponentC - public InterfaceA componentC; + class MonkeyShine + { + @Autowire!ComponentX public InterfaceA component; } - class LordOfTheComponents { - @Autowire - public InterfaceA[] components; - } - class ComponentCharlie { - @Autowire - @AssignNewInstance - public ComponentA componentA; + class BootstrapBootstrap + { + @Autowire!ComponentX public InterfaceA componentX; + + @Autowire!ComponentC public InterfaceA componentC; } - class OuttaTime { - @Autowire - @OptionalDependency - public InterfaceA interfaceA; - - @Autowire - @OptionalDependency - public ComponentA componentA; - - @Autowire - @OptionalDependency - public ComponentC[] componentCs; + class LordOfTheComponents + { + @Autowire public InterfaceA[] components; } - class ValuedClass { + class ComponentCharlie + { + @Autowire @AssignNewInstance public ComponentA componentA; + } + + class OuttaTime + { + @Autowire @OptionalDependency public InterfaceA interfaceA; + + @Autowire @OptionalDependency public ComponentA componentA; + + @Autowire @OptionalDependency public ComponentC[] componentCs; + } + + class ValuedClass + { @Value("values.int") public int intValue; - @Autowire - public ComponentA unrelated; + @Autowire public ComponentA unrelated; } - class TestInjector : ValueInjector!int { - public override int get(string key) { + class TestInjector : ValueInjector!int + { + public override int get(string key) + { assert(key == "values.int"); return 8; } } - interface TestInterface {} - - class TestClass : TestInterface { + interface TestInterface + { } - class TestClassDeux : TestInterface { - @Autowire - public UnrelatedClass unrelated; + class TestClass : TestInterface + { } - class UnrelatedClass{ + class TestClassDeux : TestInterface + { + @Autowire public UnrelatedClass unrelated; } - class FailOnCreationClass { - this() { + class UnrelatedClass + { + } + + class FailOnCreationClass + { + this() + { throw new Exception("This class should not be instantiated"); } } - class AutowiredClass { + class AutowiredClass + { } - class ComponentClass { - @Autowire - public AutowiredClass autowiredClass; + class ComponentClass + { + @Autowire public AutowiredClass autowiredClass; } - class ComponentCat { - @Autowire - public ComponentMouse mouse; + class ComponentCat + { + @Autowire public ComponentMouse mouse; } - class ComponentMouse { - @Autowire - public ComponentCat cat; + class ComponentMouse + { + @Autowire public ComponentCat cat; } - class Eenie { - @Autowire - public Meenie meenie; + class Eenie + { + @Autowire public Meenie meenie; } - class Meenie { - @Autowire - public Moe moe; + class Meenie + { + @Autowire public Moe moe; } - class Moe { - @Autowire - public Eenie eenie; + class Moe + { + @Autowire public Eenie eenie; } - class Ittie { - @Autowire - public Bittie bittie; + class Ittie + { + @Autowire public Bittie bittie; } - class Bittie { - @Autowire - public Bunena banana; + class Bittie + { + @Autowire public Bunena banana; } - class Bunena { - @Autowire - public Bittie bittie; + class Bunena + { + @Autowire public Bittie bittie; } - interface SuperInterface { + interface SuperInterface + { } - class SuperImplementation : SuperInterface { - @Autowire - public Bunena banana; + class SuperImplementation : SuperInterface + { + @Autowire public Bunena banana; } - interface Color { + interface Color + { } - class Blue : Color { + class Blue : Color + { } - class Red : Color { + class Red : Color + { } - class Spiders { - @Autowire - public TestInterface testMember; + class Spiders + { + @Autowire public TestInterface testMember; } - class Recursive { - @Autowire - public Recursive recursive; + class Recursive + { + @Autowire public Recursive recursive; } - class Moolah {} - - class Wants { - @Autowire - public Moolah moolah; + class Moolah + { } - class John { - @Autowire - public Wants wants; + class Wants + { + @Autowire public Moolah moolah; } - class Cocktail { - @Autowire - public Moolah moolah; + class John + { + @Autowire public Wants wants; + } + + class Cocktail + { + @Autowire public Moolah moolah; public Red red; - this(Red red) { + this(Red red) + { this.red = red; } } - class Wallpaper { + class Wallpaper + { public Color color; - this(Color color) { + this(Color color) + { this.color = color; } } - class Pot { - this(Kettle kettle) {} + class Pot + { + this(Kettle kettle) + { + } } - class Kettle { - this(Pot pot) {} + class Kettle + { + this(Pot pot) + { + } } - class Rock { - this(Scissors scissors) {} + class Rock + { + this(Scissors scissors) + { + } } - class Paper { - this(Rock rock) {} + class Paper + { + this(Rock rock) + { + } } - class Scissors { - this(Paper paper) {} + class Scissors + { + this(Paper paper) + { + } } - class Hello { - this(Ola ola) {} + class Hello + { + this(Ola ola) + { + } } - class PostConstructionDependency { + class PostConstructionDependency + { public bool postConstructWasCalled = false; - @PostConstruct - public void callMeMaybe() { + @PostConstruct public void callMeMaybe() + { postConstructWasCalled = true; } } - class ChildOfPostConstruction : PostConstructionDependency {} - - interface ThereWillBePostConstruction { - @PostConstruct - void constructIt(); + class ChildOfPostConstruction : PostConstructionDependency + { } - class ButThereWontBe : ThereWillBePostConstruction { + interface ThereWillBePostConstruction + { + @PostConstruct void constructIt(); + } + + class ButThereWontBe : ThereWillBePostConstruction + { public bool postConstructWasCalled = false; - public override void constructIt() { + public override void constructIt() + { postConstructWasCalled = true; } } - class PostConstructWithAutowiring { - @Autowire - private PostConstructionDependency dependency; + class PostConstructWithAutowiring + { + @Autowire private PostConstructionDependency dependency; @Value("") private int theNumber = 1; - @PostConstruct - public void doIt() { + @PostConstruct public void doIt() + { assert(theNumber == 8783); assert(dependency !is null); } } - class PreDestroyerOfFates { + class PreDestroyerOfFates + { public bool preDestroyWasCalled = false; - @PreDestroy - public void callMeMaybe() { + @PreDestroy public void callMeMaybe() + { preDestroyWasCalled = true; } } - class PostConstructingIntInjector : ValueInjector!int { - int get(string key) { + class PostConstructingIntInjector : ValueInjector!int + { + int get(string key) + { return 8783; } } - interface Fruit { + interface Fruit + { string getShape(); } - interface Animal { + interface Animal + { string getYell(); } - class Banana { + class Banana + { public string color; - this(string color) { + this(string color) + { this.color = color; } } - class Apple {} + class Apple + { + } - class Pear : Fruit { - public override string getShape() { + class Pear : Fruit + { + public override string getShape() + { return "Pear shaped"; } } - class Rabbit : Animal { - public override string getYell() { + class Rabbit : Animal + { + public override string getYell() + { return "Squeeeeeel"; } } - class Wolf : Animal { - public override string getYell() { + class Wolf : Animal + { + public override string getYell() + { return "Wooooooooooo"; } } - class PieChart {} + class PieChart + { + } - class CakeChart : PieChart {} + class CakeChart : PieChart + { + } - class ClassWrapper { + class ClassWrapper + { public Object someClass; - this(Object someClass) { + this(Object someClass) + { this.someClass = someClass; } } - class ClassWrapperWrapper { + class ClassWrapperWrapper + { public ClassWrapper wrapper; - this(ClassWrapper wrapper) { + this(ClassWrapper wrapper) + { this.wrapper = wrapper; } } - class SimpleContext : ApplicationContext { - public override void registerDependencies(shared(DependencyContainer) container) { + class SimpleContext : ApplicationContext + { + public override void registerDependencies(shared(DependencyContainer) container) + { container.register!CakeChart; } - @Component - public Apple apple() { + @Component public Apple apple() + { return new Apple(); } } - class ComplexAutowiredTestContext : ApplicationContext { + class ComplexAutowiredTestContext : ApplicationContext + { - @Autowire - private Apple apple; + @Autowire private Apple apple; - @Autowire - protected ClassWrapper classWrapper; + @Autowire protected ClassWrapper classWrapper; - public override void registerDependencies(shared(DependencyContainer) container) { + public override void registerDependencies(shared(DependencyContainer) container) + { container.register!Apple; } - @Component - public ClassWrapper wrapper() { + @Component public ClassWrapper wrapper() + { return new ClassWrapper(apple); } - @Component - public ClassWrapperWrapper wrapperWrapper() { + @Component public ClassWrapperWrapper wrapperWrapper() + { return new ClassWrapperWrapper(classWrapper); } } - class AutowiredTestContext : ApplicationContext { + class AutowiredTestContext : ApplicationContext + { - @Autowire - private Apple apple; + @Autowire private Apple apple; - @Component - public ClassWrapper wrapper() { + @Component public ClassWrapper wrapper() + { return new ClassWrapper(apple); } } - class TestContext : ApplicationContext { + class TestContext : ApplicationContext + { - @Component - public Banana banana() { + @Component public Banana banana() + { return new Banana("Yellow"); } - public Apple apple() { + public Apple apple() + { return new Apple(); } - @Component - @RegisterByType!Fruit - public Pear pear() { + @Component @RegisterByType!Fruit public Pear pear() + { return new Pear(); } - @Component - @RegisterByType!Animal - public Rabbit rabbit() { + @Component @RegisterByType!Animal public Rabbit rabbit() + { return new Rabbit(); } - @Component - @RegisterByType!Animal - public Wolf wolf() { + @Component @RegisterByType!Animal public Wolf wolf() + { return new Wolf(); } - @Component - @Prototype - public PieChart pieChart() { + @Component @Prototype public PieChart pieChart() + { return new PieChart(); } } - class TestImplementation : TestInterface { + class TestImplementation : TestInterface + { public string someContent = ""; } - class SomeOtherClassThen { + class SomeOtherClassThen + { } - class ClassWithConstructor { + class ClassWithConstructor + { public TestImplementation testImplementation; - this(TestImplementation testImplementation) { + this(TestImplementation testImplementation) + { this.testImplementation = testImplementation; } } - class ClassWithMultipleConstructors { + class ClassWithMultipleConstructors + { public SomeOtherClassThen someOtherClassThen; public TestImplementation testImplementation; - this(SomeOtherClassThen someOtherClassThen) { + this(SomeOtherClassThen someOtherClassThen) + { this.someOtherClassThen = someOtherClassThen; } - this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { + this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) + { this.someOtherClassThen = someOtherClassThen; this.testImplementation = testImplementation; } } - class ClassWithConstructorWithMultipleParameters { + class ClassWithConstructorWithMultipleParameters + { public SomeOtherClassThen someOtherClassThen; public TestImplementation testImplementation; - this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) { + this(SomeOtherClassThen someOtherClassThen, TestImplementation testImplementation) + { this.someOtherClassThen = someOtherClassThen; this.testImplementation = testImplementation; } } - class ClassWithPrimitiveConstructor { + class ClassWithPrimitiveConstructor + { public SomeOtherClassThen someOtherClassThen; - this(string willNotBePicked) { + this(string willNotBePicked) + { } - this(SomeOtherClassThen someOtherClassThen) { + this(SomeOtherClassThen someOtherClassThen) + { this.someOtherClassThen = someOtherClassThen; } } - class ClassWithEmptyConstructor { + class ClassWithEmptyConstructor + { public SomeOtherClassThen someOtherClassThen; - this() { + this() + { } - this(SomeOtherClassThen someOtherClassThen) { + this(SomeOtherClassThen someOtherClassThen) + { this.someOtherClassThen = someOtherClassThen; } } - class ClassWithNonInjectableConstructor { - this(string myName) { + class ClassWithNonInjectableConstructor + { + this(string myName) + { } } - class ClassWithStructConstructor { + class ClassWithStructConstructor + { public SomeOtherClassThen someOtherClassThen; - this(Thing willNotBePicked) { + this(Thing willNotBePicked) + { } - this(SomeOtherClassThen someOtherClassThen) { + this(SomeOtherClassThen someOtherClassThen) + { this.someOtherClassThen = someOtherClassThen; } } - class TestType {} + class TestType + { + } - class Dependency {} + class Dependency + { + } - struct Thing { + struct Thing + { int x; } - class MyConfig { + class MyConfig + { @Value("conf.stuffs") int stuffs; @@ -543,85 +644,105 @@ version(unittest) { Thing thing; } - class ConfigWithDefaults { + class ConfigWithDefaults + { @Value("conf.missing") int noms = 9; } - class ConfigWithMandatory { + class ConfigWithMandatory + { @MandatoryValue("conf.mustbethere") int nums; } - class IntInjector : ValueInjector!int { - public override int get(string key) { + class IntInjector : ValueInjector!int + { + public override int get(string key) + { assert(key == "conf.stuffs"); return 364; } } - class StringInjector : ValueInjector!string { - public override string get(string key) { + class StringInjector : ValueInjector!string + { + public override string get(string key) + { assert(key == "conf.name"); return "Le Chef"; } } - class ThingInjector : ValueInjector!Thing { - public override Thing get(string key) { + class ThingInjector : ValueInjector!Thing + { + public override Thing get(string key) + { assert(key == "conf.thing"); return Thing(8899); } } - class DefaultIntInjector : ValueInjector!int { - public override int get(string key) { + class DefaultIntInjector : ValueInjector!int + { + public override int get(string key) + { throw new ValueNotAvailableException(key); } } - class MandatoryAvailableIntInjector : ValueInjector!int { - public override int get(string key) { + class MandatoryAvailableIntInjector : ValueInjector!int + { + public override int get(string key) + { return 7466; } } - class MandatoryUnavailableIntInjector : ValueInjector!int { - public override int get(string key) { + class MandatoryUnavailableIntInjector : ValueInjector!int + { + public override int get(string key) + { throw new ValueNotAvailableException(key); } } - class DependencyInjectedIntInjector : ValueInjector!int { - @Autowire - public Dependency dependency; + class DependencyInjectedIntInjector : ValueInjector!int + { + @Autowire public Dependency dependency; - public override int get(string key) { + public override int get(string key) + { return 2345; } } - class CircularIntInjector : ValueInjector!int { - @Autowire - public ValueInjector!int dependency; + class CircularIntInjector : ValueInjector!int + { + @Autowire public ValueInjector!int dependency; private int count = 0; - public override int get(string key) { + public override int get(string key) + { count += 1; - if (count >= 3) { + if (count >= 3) + { return count; } return dependency.get(key); } } - class ValueInjectedIntInjector : ValueInjector!int { + class ValueInjectedIntInjector : ValueInjector!int + { @Value("five") public int count = 0; - public override int get(string key) { - if (key == "five") { + public override int get(string key) + { + if (key == "five") + { return 5; } @@ -629,12 +750,14 @@ version(unittest) { } } - class DependencyValueInjectedIntInjector : ValueInjector!int { - @Autowire - public ConfigWithDefaults config; + class DependencyValueInjectedIntInjector : ValueInjector!int + { + @Autowire public ConfigWithDefaults config; - public override int get(string key) { - if (key == "conf.missing") { + public override int get(string key) + { + if (key == "conf.missing") + { return 8899; } @@ -642,16 +765,18 @@ version(unittest) { } } - class TemplatedComponent(T) { - @Autowire - T instance; + class TemplatedComponent(T) + { + @Autowire T instance; } - class CircularTemplateComponentA : TemplatedComponent!CircularTemplateComponentB { + class CircularTemplateComponentA : TemplatedComponent!CircularTemplateComponentB + { } - class CircularTemplateComponentB : TemplatedComponent!CircularTemplateComponentA { + class CircularTemplateComponentB : TemplatedComponent!CircularTemplateComponentA + { } } diff --git a/test/poodinis/testmain.d b/test/poodinis/testmain.d index 7fc43bc..e76b1bc 100644 --- a/test/poodinis/testmain.d +++ b/test/poodinis/testmain.d @@ -5,4 +5,6 @@ * The full terms of the license can be found in the LICENSE file. */ -void main() {} +void main() +{ +} diff --git a/test/poodinis/valueinjectiontest.d b/test/poodinis/valueinjectiontest.d index 8a57db6..2578283 100644 --- a/test/poodinis/valueinjectiontest.d +++ b/test/poodinis/valueinjectiontest.d @@ -10,26 +10,32 @@ import poodinis.test.testClasses; import std.exception; -version(unittest) { +version (unittest) +{ - struct LocalStruct { + struct LocalStruct + { bool wasInjected = false; } - class LocalStructInjector : ValueInjector!LocalStruct { - public override LocalStruct get(string key) { + class LocalStructInjector : ValueInjector!LocalStruct + { + public override LocalStruct get(string key) + { auto data = LocalStruct(true); return data; } } - class LocalClassWithStruct { + class LocalClassWithStruct + { @Value("") public LocalStruct localStruct; } // Test injection of values - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!MyConfig; container.register!(ValueInjector!int, IntInjector); @@ -43,7 +49,8 @@ version(unittest) { } // Test injection of values throws exception when injector is not there - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!MyConfig; assertThrown!ResolveException(container.resolve!MyConfig); @@ -52,7 +59,8 @@ version(unittest) { } // Test injection of values with defaults - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ConfigWithDefaults; container.register!(ValueInjector!int, DefaultIntInjector); @@ -62,7 +70,8 @@ version(unittest) { } // Test mandatory injection of values which are available - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ConfigWithMandatory; container.register!(ValueInjector!int, MandatoryAvailableIntInjector); @@ -72,7 +81,8 @@ version(unittest) { } // Test mandatory injection of values which are not available - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ConfigWithMandatory; container.register!(ValueInjector!int, MandatoryUnavailableIntInjector); @@ -82,7 +92,8 @@ version(unittest) { } // Test injecting dependencies within value injectors - unittest { + unittest + { auto container = new shared DependencyContainer(); auto dependency = new Dependency(); container.register!Dependency.existingInstance(dependency); @@ -93,7 +104,8 @@ version(unittest) { } // Test injecting circular dependencies within value injectors - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(ValueInjector!int, CircularIntInjector); auto injector = cast(CircularIntInjector) container.resolve!(ValueInjector!int); @@ -103,7 +115,8 @@ version(unittest) { } // Test value injection within value injectors - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(ValueInjector!int, ValueInjectedIntInjector); auto injector = cast(ValueInjectedIntInjector) container.resolve!(ValueInjector!int); @@ -112,18 +125,21 @@ version(unittest) { } // Test value injection within dependencies of value injectors - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!ConfigWithDefaults; container.register!(ValueInjector!int, DependencyValueInjectedIntInjector); - auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!(ValueInjector!int); + auto injector = cast(DependencyValueInjectedIntInjector) container.resolve!( + ValueInjector!int); assert(injector.config.noms == 8899); } // Test resolving locally defined struct injector (github issue #20) - unittest { + unittest + { auto container = new shared DependencyContainer(); container.register!(ValueInjector!LocalStruct, LocalStructInjector); container.register!LocalClassWithStruct;