Deprecate singleton factory method

The factory method encourages misuse of dependency injection (by using it as a service locator). Removing the factory method forces the user to make this choice deliberately.
This commit is contained in:
Mike Bierlee 2016-08-08 22:17:17 +02:00
parent 02dbe20c64
commit 9e5a27d046
13 changed files with 311 additions and 308 deletions

View file

@ -4,6 +4,9 @@ Poodinis Changelog
* REMOVE deprecated registration options. They are still available in properly cased forms. * REMOVE deprecated registration options. They are still available in properly cased forms.
* REMOVE deprecated register() and resolve() methods which accept variadics and arrays for options. * REMOVE deprecated register() and resolve() methods which accept variadics and arrays for options.
Since registration and resolve options have become bitfields, you should specify them with logical ANDs. Since registration and resolve options have become bitfields, you should specify them with logical ANDs.
* DEPRECATE DependencyContainer.getInstance(). To properly make use of inversion of control, one should only
create the dependency container once during set-up and then completly rely on injection. See examples for
proper usage. You can still create your own singleton factory (method) if this is crucial to your design.
**Version 6.3.0** **Version 6.3.0**
* CHANGE registration and resolve options to be supplied using bit flags instead. (Thanks to tmccombs) * CHANGE registration and resolve options to be supplied using bit flags instead. (Thanks to tmccombs)

View file

@ -35,7 +35,7 @@ class DataWriter {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
dependencies.register!DataWriter; dependencies.register!DataWriter;
dependencies.register!(Database, RelationalDatabase); dependencies.register!(Database, RelationalDatabase);

View file

@ -6,11 +6,10 @@ The container
------------- -------------
To register a class, a new dependency container must be instantiated: To register a class, a new dependency container must be instantiated:
```d ```d
// Register a private container // Create a shared container
shared(DependencyContainer) dependencies = new DependencyContainer(); auto dependencies = new shared DependencyContainer();
// Or use the singleton container
dependencies = DependencyContainer.getInstance();
``` ```
A shared dependency container is thread-safe and resolves the same dependencies across all threads.
###Registering dependencies ###Registering dependencies
To make dependencies available, they have to be registered: To make dependencies available, they have to be registered:
```d ```d

View file

@ -53,7 +53,7 @@ class SecurityManager {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope dependencies.register!SuperSecurityDevice; // Registered with the default "Single instance" scope
dependencies.register!SecurityManager; dependencies.register!SecurityManager;

View file

@ -60,7 +60,7 @@ class ExampleApplicationContext : ApplicationContext {
} }
void main() { void main() {
auto container = DependencyContainer.getInstance(); auto container = new shared DependencyContainer();
container.registerContext!ExampleApplicationContext; container.registerContext!ExampleApplicationContext;
auto townSquare = container.resolve!TownSquare; auto townSquare = container.resolve!TownSquare;

View file

@ -43,7 +43,7 @@ class PieEater {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
dependencies.register!(Pie, BlueBerryPie); dependencies.register!(Pie, BlueBerryPie);
dependencies.register!(Pie, ApplePie); dependencies.register!(Pie, ApplePie);
dependencies.register!(Pie, CardboardBoxPie); dependencies.register!(Pie, CardboardBoxPie);

View file

@ -44,7 +44,7 @@ class HybridCar {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
dependencies.register!HybridCar; dependencies.register!HybridCar;
dependencies.register!(Engine, FuelEngine); dependencies.register!(Engine, FuelEngine);

View file

@ -16,7 +16,7 @@ class DataWriter {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
dependencies.register!DataWriter; dependencies.register!DataWriter;
dependencies.register!(Database, RelationalDatabase); dependencies.register!(Database, RelationalDatabase);

View file

@ -26,7 +26,7 @@ class Orchestra {
} }
void main() { void main() {
auto dependencies = DependencyContainer.getInstance(); auto dependencies = new shared DependencyContainer();
/* /*
* By using the resolve option "registerBeforeResolving" you can register the resolved class * By using the resolve option "registerBeforeResolving" you can register the resolved class

View file

@ -389,8 +389,9 @@ synchronized class DependencyContainer {
/** /**
* Returns a global singleton instance of a dependency container. * Returns a global singleton instance of a dependency container.
* Deprecated: create new instance with new keyword or implement your own singleton factory (method)
*/ */
public static shared(DependencyContainer) getInstance() { deprecated public static shared(DependencyContainer) getInstance() {
static shared DependencyContainer instance; static shared DependencyContainer instance;
if (instance is null) { if (instance is null) {
instance = new DependencyContainer(); instance = new DependencyContainer();

View file

@ -1,243 +1,243 @@
/** /**
* Poodinis Dependency Injection Framework * Poodinis Dependency Injection Framework
* Copyright 2014-2016 Mike Bierlee * Copyright 2014-2016 Mike Bierlee
* This software is licensed under the terms of the MIT license. * This software is licensed under the terms of the MIT license.
* The full terms of the license can be found in the LICENSE file. * The full terms of the license can be found in the LICENSE file.
*/ */
import poodinis; import poodinis;
import std.exception; import std.exception;
version(unittest) { version(unittest) {
class ComponentA {} class ComponentA {}
class ComponentB { class ComponentB {
public @Autowire ComponentA componentA; public @Autowire ComponentA componentA;
} }
interface InterfaceA {} interface InterfaceA {}
class ComponentC : InterfaceA {} class ComponentC : InterfaceA {}
class ComponentD { class ComponentD {
public @Autowire InterfaceA componentC = null; public @Autowire InterfaceA componentC = null;
private @Autowire InterfaceA privateComponentC = null; private @Autowire InterfaceA privateComponentC = null;
} }
class DummyAttribute{}; class DummyAttribute{};
class ComponentE { class ComponentE {
@DummyAttribute @DummyAttribute
public ComponentC componentC; public ComponentC componentC;
} }
class ComponentDeclarationCocktail { class ComponentDeclarationCocktail {
alias noomer = int; alias noomer = int;
@Autowire @Autowire
public ComponentA componentA; public ComponentA componentA;
public void doesNothing() { public void doesNothing() {
} }
~this(){ ~this(){
} }
} }
class ComponentX : InterfaceA {} class ComponentX : InterfaceA {}
class ComponentZ : ComponentB { class ComponentZ : ComponentB {
} }
class MonkeyShine { class MonkeyShine {
@Autowire!ComponentX @Autowire!ComponentX
public InterfaceA component; public InterfaceA component;
} }
class BootstrapBootstrap { class BootstrapBootstrap {
@Autowire!ComponentX @Autowire!ComponentX
public InterfaceA componentX; public InterfaceA componentX;
@Autowire!ComponentC @Autowire!ComponentC
public InterfaceA componentC; public InterfaceA componentC;
} }
class LordOfTheComponents { class LordOfTheComponents {
@Autowire @Autowire
public InterfaceA[] components; public InterfaceA[] components;
} }
class ComponentCharlie { class ComponentCharlie {
@Autowire @Autowire
@AssignNewInstance @AssignNewInstance
public ComponentA componentA; public ComponentA componentA;
} }
class OuttaTime { class OuttaTime {
@Autowire @Autowire
@OptionalDependency @OptionalDependency
public InterfaceA interfaceA; public InterfaceA interfaceA;
@Autowire @Autowire
@OptionalDependency @OptionalDependency
public ComponentA componentA; public ComponentA componentA;
@Autowire @Autowire
@OptionalDependency @OptionalDependency
public ComponentC[] componentCs; public ComponentC[] componentCs;
} }
// Test autowiring concrete type to existing instance // Test autowiring concrete type to existing instance
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentA; container.register!ComponentA;
auto componentB = new ComponentB(); auto componentB = new ComponentB();
container.autowire(componentB); container.autowire(componentB);
assert(componentB !is null, "Autowirable dependency failed to autowire"); assert(componentB !is null, "Autowirable dependency failed to autowire");
} }
// Test autowiring interface type to existing instance // Test autowiring interface type to existing instance
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentC);
auto componentD = new ComponentD(); auto componentD = new ComponentD();
container.autowire(componentD); container.autowire(componentD);
assert(componentD.componentC !is null, "Autowirable dependency failed to autowire"); assert(componentD.componentC !is null, "Autowirable dependency failed to autowire");
} }
// Test autowiring private members // Test autowiring private members
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentC);
auto componentD = new ComponentD(); auto componentD = new ComponentD();
container.autowire(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 // Test autowiring will only happen once
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC).newInstance(); container.register!(InterfaceA, ComponentC).newInstance();
auto componentD = new ComponentD(); auto componentD = new ComponentD();
container.autowire(componentD); container.autowire(componentD);
auto expectedComponent = componentD.componentC; auto expectedComponent = componentD.componentC;
container.autowire(componentD); container.autowire(componentD);
auto actualComponent = componentD.componentC; 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 // Test autowiring unregistered type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto componentD = new ComponentD(); 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 // Test autowiring member with non-autowire attribute does not autowire
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto componentE = new ComponentE(); auto componentE = new ComponentE();
container.autowire(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 // Test autowire class with alias declaration
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentA; container.register!ComponentA;
auto componentDeclarationCocktail = new ComponentDeclarationCocktail(); auto componentDeclarationCocktail = new ComponentDeclarationCocktail();
container.autowire(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 // Test autowire class with qualifier
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX); container.register!(InterfaceA, ComponentX);
auto componentX = container.resolve!(InterfaceA, ComponentX); auto componentX = container.resolve!(InterfaceA, ComponentX);
auto monkeyShine = new MonkeyShine(); auto monkeyShine = new MonkeyShine();
container.autowire(monkeyShine); container.autowire(monkeyShine);
assert(monkeyShine.component is componentX, "Autowiring class with qualifier failed"); assert(monkeyShine.component is componentX, "Autowiring class with qualifier failed");
} }
// Test autowire class with multiple qualifiers // Test autowire class with multiple qualifiers
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX); container.register!(InterfaceA, ComponentX);
auto componentC = container.resolve!(InterfaceA, ComponentC); auto componentC = container.resolve!(InterfaceA, ComponentC);
auto componentX = container.resolve!(InterfaceA, ComponentX); auto componentX = container.resolve!(InterfaceA, ComponentX);
auto bootstrapBootstrap = new BootstrapBootstrap(); auto bootstrapBootstrap = new BootstrapBootstrap();
container.autowire(bootstrapBootstrap); container.autowire(bootstrapBootstrap);
assert(bootstrapBootstrap.componentX is componentX, "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"); assert(bootstrapBootstrap.componentC is componentC, "Autowiring class with multiple qualifiers failed");
} }
// Test getting instance from autowired registration will autowire instance // Test getting instance from autowired registration will autowire instance
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentA; container.register!ComponentA;
auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), container).singleInstance(); auto registration = new AutowiredRegistration!ComponentB(typeid(ComponentB), container).singleInstance();
auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext()); auto instance = cast(ComponentB) registration.getInstance(new AutowireInstantiationContext());
assert(instance.componentA !is null); assert(instance.componentA !is null);
} }
// Test autowiring a dynamic array with all qualified types // Test autowiring a dynamic array with all qualified types
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(InterfaceA, ComponentC); container.register!(InterfaceA, ComponentC);
container.register!(InterfaceA, ComponentX); container.register!(InterfaceA, ComponentX);
auto lord = new LordOfTheComponents(); auto lord = new LordOfTheComponents();
container.autowire(lord); container.autowire(lord);
assert(lord.components.length == 2, "Dynamic array was not autowired"); assert(lord.components.length == 2, "Dynamic array was not autowired");
} }
// Test autowiring new instance of singleinstance registration with newInstance UDA // Test autowiring new instance of singleinstance registration with newInstance UDA
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentA; container.register!ComponentA;
auto regularComponentA = container.resolve!ComponentA; auto regularComponentA = container.resolve!ComponentA;
auto charlie = new ComponentCharlie(); auto charlie = new ComponentCharlie();
container.autowire(charlie); 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 // Test autowiring members from base class
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentA; container.register!ComponentA;
container.register!ComponentB; container.register!ComponentB;
container.register!ComponentZ; container.register!ComponentZ;
auto instance = new ComponentZ(); auto instance = new ComponentZ();
container.autowire(instance); container.autowire(instance);
assert(instance.componentA !is null); assert(instance.componentA !is null);
} }
// Test autowiring optional depenencies // Test autowiring optional depenencies
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto instance = new OuttaTime(); auto instance = new OuttaTime();
container.autowire(instance); container.autowire(instance);
assert(instance.interfaceA is null); assert(instance.interfaceA is null);
assert(instance.componentA is null); assert(instance.componentA is null);
assert(instance.componentCs is null); assert(instance.componentCs is null);
} }
} }

View file

@ -182,14 +182,14 @@ version(unittest) {
// Test register concrete type // Test register concrete type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto registration = container.register!TestClass; 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 // Test resolve registered type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass; container.register!TestClass;
TestClass actualInstance = container.resolve!TestClass; TestClass actualInstance = container.resolve!TestClass;
assert(actualInstance !is null, "Resolved type is null"); assert(actualInstance !is null, "Resolved type is null");
@ -198,7 +198,7 @@ version(unittest) {
// Test register interface // Test register interface
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(TestInterface, TestClass); container.register!(TestInterface, TestClass);
TestInterface actualInstance = container.resolve!TestInterface; TestInterface actualInstance = container.resolve!TestInterface;
assert(actualInstance !is null, "Resolved type is null"); assert(actualInstance !is null, "Resolved type is null");
@ -207,19 +207,19 @@ version(unittest) {
// Test resolve non-registered type // Test resolve non-registered type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); 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 // Test clear registrations
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass; container.register!TestClass;
container.clearAllRegistrations(); 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 get singleton of container // Test get singleton of container (DEPRECATED)
unittest { unittest {
auto instance1 = DependencyContainer.getInstance(); auto instance1 = DependencyContainer.getInstance();
auto instance2 = DependencyContainer.getInstance(); auto instance2 = DependencyContainer.getInstance();
@ -228,7 +228,7 @@ version(unittest) {
// Test resolve single instance for type // Test resolve single instance for type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass.singleInstance(); container.register!TestClass.singleInstance();
auto instance1 = container.resolve!TestClass; auto instance1 = container.resolve!TestClass;
auto instance2 = container.resolve!TestClass; auto instance2 = container.resolve!TestClass;
@ -237,7 +237,7 @@ version(unittest) {
// Test resolve new instance for type // Test resolve new instance for type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass.newInstance(); container.register!TestClass.newInstance();
auto instance1 = container.resolve!TestClass; auto instance1 = container.resolve!TestClass;
auto instance2 = container.resolve!TestClass; auto instance2 = container.resolve!TestClass;
@ -246,7 +246,7 @@ version(unittest) {
// Test resolve existing instance for type // Test resolve existing instance for type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto expectedInstance = new TestClass(); auto expectedInstance = new TestClass();
container.register!TestClass.existingInstance(expectedInstance); container.register!TestClass.existingInstance(expectedInstance);
auto actualInstance = container.resolve!TestClass; auto actualInstance = container.resolve!TestClass;
@ -255,7 +255,7 @@ version(unittest) {
// Test autowire resolved instances // Test autowire resolved instances
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!AutowiredClass; container.register!AutowiredClass;
container.register!ComponentClass; container.register!ComponentClass;
auto componentInstance = container.resolve!ComponentClass; auto componentInstance = container.resolve!ComponentClass;
@ -265,7 +265,7 @@ version(unittest) {
// Test circular autowiring // Test circular autowiring
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!ComponentMouse; container.register!ComponentMouse;
container.register!ComponentCat; container.register!ComponentCat;
auto mouse = container.resolve!ComponentMouse; auto mouse = container.resolve!ComponentMouse;
@ -275,7 +275,7 @@ version(unittest) {
// Test remove registration // Test remove registration
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass; container.register!TestClass;
container.removeRegistration!TestClass; container.removeRegistration!TestClass;
assertThrown!ResolveException(container.resolve!TestClass); assertThrown!ResolveException(container.resolve!TestClass);
@ -283,7 +283,7 @@ version(unittest) {
// Test autowiring does not autowire member where instance is non-null // Test autowiring does not autowire member where instance is non-null
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto existingA = new AutowiredClass(); auto existingA = new AutowiredClass();
auto existingB = new ComponentClass(); auto existingB = new ComponentClass();
existingB.autowiredClass = existingA; existingB.autowiredClass = existingA;
@ -298,7 +298,7 @@ version(unittest) {
// Test autowiring circular dependency by third-degree // Test autowiring circular dependency by third-degree
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Eenie; container.register!Eenie;
container.register!Meenie; container.register!Meenie;
container.register!Moe; container.register!Moe;
@ -310,7 +310,7 @@ version(unittest) {
// Test autowiring deep circular dependencies // Test autowiring deep circular dependencies
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Ittie; container.register!Ittie;
container.register!Bittie; container.register!Bittie;
container.register!Banana; container.register!Banana;
@ -322,7 +322,7 @@ version(unittest) {
// Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time // Test autowiring deep circular dependencies with newInstance scope does not autowire new instance second time
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Ittie.newInstance(); container.register!Ittie.newInstance();
container.register!Bittie.newInstance(); container.register!Bittie.newInstance();
container.register!Banana.newInstance(); container.register!Banana.newInstance();
@ -334,7 +334,7 @@ version(unittest) {
// Test autowiring type registered by interface // Test autowiring type registered by interface
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Banana; container.register!Banana;
container.register!Bittie; container.register!Bittie;
container.register!(SuperInterface, SuperImplementation); container.register!(SuperInterface, SuperImplementation);
@ -346,7 +346,7 @@ version(unittest) {
// Test reusing a container after clearing all registrations // Test reusing a container after clearing all registrations
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Banana; container.register!Banana;
container.clearAllRegistrations(); container.clearAllRegistrations();
try { try {
@ -360,14 +360,14 @@ version(unittest) {
// Test register multiple concrete classess to same interface type // Test register multiple concrete classess to same interface type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(Color, Blue); container.register!(Color, Blue);
container.register!(Color, Red); container.register!(Color, Red);
} }
// Test removing all registrations for type with multiple registrations. // Test removing all registrations for type with multiple registrations.
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(Color, Blue); container.register!(Color, Blue);
container.register!(Color, Red); container.register!(Color, Red);
container.removeRegistration!Color; container.removeRegistration!Color;
@ -375,7 +375,7 @@ version(unittest) {
// Test registering same registration again // Test registering same registration again
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto firstRegistration = container.register!(Color, Blue); auto firstRegistration = container.register!(Color, Blue);
auto secondRegistration = container.register!(Color, Blue); auto secondRegistration = container.register!(Color, Blue);
@ -384,7 +384,7 @@ version(unittest) {
// Test resolve registration with multiple qualifiers // Test resolve registration with multiple qualifiers
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(Color, Blue); container.register!(Color, Blue);
container.register!(Color, Red); container.register!(Color, Red);
try { try {
@ -397,7 +397,7 @@ version(unittest) {
// Test resolve registration with multiple qualifiers using a qualifier // Test resolve registration with multiple qualifiers using a qualifier
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(Color, Blue); container.register!(Color, Blue);
container.register!(Color, Red); container.register!(Color, Red);
auto blueInstance = container.resolve!(Color, Blue); auto blueInstance = container.resolve!(Color, Blue);
@ -410,7 +410,7 @@ version(unittest) {
// Test autowire of unqualified member typed by interface. // Test autowire of unqualified member typed by interface.
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Spiders; container.register!Spiders;
container.register!(TestInterface, TestClass); container.register!(TestInterface, TestClass);
@ -421,7 +421,7 @@ version(unittest) {
// Register existing registration // Register existing registration
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto firstRegistration = container.register!TestClass; auto firstRegistration = container.register!TestClass;
auto secondRegistration = container.register!TestClass; auto secondRegistration = container.register!TestClass;
@ -431,7 +431,7 @@ version(unittest) {
// Register existing registration by supertype // Register existing registration by supertype
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto firstRegistration = container.register!(TestInterface, TestClass); auto firstRegistration = container.register!(TestInterface, TestClass);
auto secondRegistration = container.register!(TestInterface, TestClass); auto secondRegistration = container.register!(TestInterface, TestClass);
@ -441,7 +441,7 @@ version(unittest) {
// Resolve dependency depending on itself // Resolve dependency depending on itself
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Recursive; container.register!Recursive;
auto instance = container.resolve!Recursive; auto instance = container.resolve!Recursive;
@ -452,7 +452,7 @@ version(unittest) {
// Test autowire stack pop-back // Test autowire stack pop-back
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!Moolah; container.register!Moolah;
container.register!Wants.newInstance(); container.register!Wants.newInstance();
container.register!John; container.register!John;
@ -465,7 +465,7 @@ version(unittest) {
// Test resolving registration registered in different thread // Test resolving registration registered in different thread
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto thread = new Thread(delegate() { auto thread = new Thread(delegate() {
container.register!TestClass; container.register!TestClass;
@ -478,7 +478,7 @@ version(unittest) {
// Test resolving instance previously resolved in different thread // Test resolving instance previously resolved in different thread
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
shared(TestClass) actualTestClass; shared(TestClass) actualTestClass;
container.register!TestClass; container.register!TestClass;
@ -496,7 +496,7 @@ version(unittest) {
// Test registering type with option doNotAddConcreteTypeRegistration // Test registering type with option doNotAddConcreteTypeRegistration
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration); container.register!(TestInterface, TestClass)(RegistrationOption.doNotAddConcreteTypeRegistration);
auto firstInstance = container.resolve!TestInterface; auto firstInstance = container.resolve!TestInterface;
@ -505,14 +505,14 @@ version(unittest) {
// Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing // Test registering conrete type with registration option doNotAddConcreteTypeRegistration does nothing
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration); container.register!TestClass(RegistrationOption.doNotAddConcreteTypeRegistration);
container.resolve!TestClass; container.resolve!TestClass;
} }
// Test registering type will register by contrete type by default // Test registering type will register by contrete type by default
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(TestInterface, TestClass); container.register!(TestInterface, TestClass);
auto firstInstance = container.resolve!TestInterface; auto firstInstance = container.resolve!TestInterface;
@ -523,7 +523,7 @@ version(unittest) {
// Test resolving all registrations to an interface // Test resolving all registrations to an interface
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!(Color, Blue); container.register!(Color, Blue);
container.register!(Color, Red); container.register!(Color, Red);
@ -534,7 +534,7 @@ version(unittest) {
// Test autowiring instances resolved in array // Test autowiring instances resolved in array
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!UnrelatedClass; container.register!UnrelatedClass;
container.register!(TestInterface, TestClassDeux); container.register!(TestInterface, TestClassDeux);
@ -546,7 +546,7 @@ version(unittest) {
// Test setting up simple dependencies through application context // Test setting up simple dependencies through application context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.registerContext!TestContext; container.registerContext!TestContext;
auto instance = container.resolve!TestClass; auto instance = container.resolve!TestClass;
@ -555,7 +555,7 @@ version(unittest) {
// Test resolving dependency from registered application context // Test resolving dependency from registered application context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.registerContext!TestContext; container.registerContext!TestContext;
auto instance = container.resolve!UnrelatedClass; auto instance = container.resolve!UnrelatedClass;
@ -564,7 +564,7 @@ version(unittest) {
// Test autowiring application context // Test autowiring application context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.register!UnrelatedClass; container.register!UnrelatedClass;
container.registerContext!AutowiredTestContext; container.registerContext!AutowiredTestContext;
auto instance = container.resolve!ClassWrapper; auto instance = container.resolve!ClassWrapper;
@ -575,7 +575,7 @@ version(unittest) {
// Test autowiring application context with dependencies registered in same context // Test autowiring application context with dependencies registered in same context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.registerContext!ComplexAutowiredTestContext; container.registerContext!ComplexAutowiredTestContext;
auto instance = container.resolve!ClassWrapperWrapper; auto instance = container.resolve!ClassWrapperWrapper;
auto wrapper = container.resolve!ClassWrapper; auto wrapper = container.resolve!ClassWrapper;
@ -588,14 +588,14 @@ version(unittest) {
// Test resolving registered context // Test resolving registered context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.registerContext!TestContext; container.registerContext!TestContext;
container.resolve!ApplicationContext; container.resolve!ApplicationContext;
} }
// Test set persistent registration options // Test set persistent registration options
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration);
container.register!(TestInterface, TestClass); container.register!(TestInterface, TestClass);
assertThrown!ResolveException(container.resolve!TestClass); assertThrown!ResolveException(container.resolve!TestClass);
@ -603,7 +603,7 @@ version(unittest) {
// Test unset persistent registration options // Test unset persistent registration options
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration); container.setPersistentRegistrationOptions(RegistrationOption.doNotAddConcreteTypeRegistration);
container.unsetPersistentRegistrationOptions(); container.unsetPersistentRegistrationOptions();
container.register!(TestInterface, TestClass); container.register!(TestInterface, TestClass);
@ -612,21 +612,21 @@ version(unittest) {
// Test registration when resolving // Test registration when resolving
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving); container.resolve!(TestInterface, TestClass)(ResolveOption.registerBeforeResolving);
container.resolve!TestClass; container.resolve!TestClass;
} }
// Test set persistent resolve options // Test set persistent resolve options
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
container.resolve!TestClass; container.resolve!TestClass;
} }
// Test unset persistent resolve options // Test unset persistent resolve options
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving); container.setPersistentResolveOptions(ResolveOption.registerBeforeResolving);
container.unsetPersistentResolveOptions(); container.unsetPersistentResolveOptions();
assertThrown!ResolveException(container.resolve!TestClass); assertThrown!ResolveException(container.resolve!TestClass);
@ -634,20 +634,20 @@ version(unittest) {
// Test ResolveOption registerBeforeResolving fails for interfaces // Test ResolveOption registerBeforeResolving fails for interfaces
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); 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 // Test ResolveOption noResolveException does not throw
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto instance = container.resolve!TestInterface(ResolveOption.noResolveException); auto instance = container.resolve!TestInterface(ResolveOption.noResolveException);
assert(instance is null); assert(instance is null);
} }
// ResolveOption noResolveException does not throw for resolveAll // ResolveOption noResolveException does not throw for resolveAll
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException); auto instances = container.resolveAll!TestInterface(ResolveOption.noResolveException);
assert(instances.length == 0); assert(instances.length == 0);
} }

View file

@ -87,7 +87,7 @@ version(unittest) {
//Test register component registrations from context //Test register component registrations from context
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto context = new TestContext(); auto context = new TestContext();
context.registerContextComponents(container); context.registerContextComponents(container);
auto bananaInstance = container.resolve!Banana; auto bananaInstance = container.resolve!Banana;
@ -97,7 +97,7 @@ version(unittest) {
//Test non-annotated methods are not registered //Test non-annotated methods are not registered
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto context = new TestContext(); auto context = new TestContext();
context.registerContextComponents(container); context.registerContextComponents(container);
assertThrown!ResolveException(container.resolve!Apple); assertThrown!ResolveException(container.resolve!Apple);
@ -105,7 +105,7 @@ version(unittest) {
//Test register component by base type //Test register component by base type
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto context = new TestContext(); auto context = new TestContext();
context.registerContextComponents(container); context.registerContextComponents(container);
auto instance = container.resolve!Fruit; auto instance = container.resolve!Fruit;
@ -114,7 +114,7 @@ version(unittest) {
//Test register components with multiple candidates //Test register components with multiple candidates
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto context = new TestContext(); auto context = new TestContext();
context.registerContextComponents(container); context.registerContextComponents(container);
@ -127,7 +127,7 @@ version(unittest) {
//Test register component as prototype //Test register component as prototype
unittest { unittest {
shared(DependencyContainer) container = new DependencyContainer(); auto container = new shared DependencyContainer();
auto context = new TestContext(); auto context = new TestContext();
context.registerContextComponents(container); context.registerContextComponents(container);