diff --git a/CHANGES.md b/CHANGES.md index 4bd97c6..db05c47 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ Poodinis Changelog ================== **Version 7.0.0** +* ADD constructor injection. Injection is done automatically on resolve. See tutorial and examples for more details. * 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. Since registration and resolve options have become bitfields, you should specify them with logical ANDs. diff --git a/README.md b/README.md index 21e2511..d3bffdb 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Licensed under the terms of the MIT license - See [LICENSE.txt](LICENSE.txt) Master: [![Build Status](https://api.travis-ci.org/mbierlee/poodinis.png?branch=master)](https://travis-ci.org/mbierlee/poodinis) - Dev: [![Build Status](https://api.travis-ci.org/mbierlee/poodinis.png?branch=develop)](https://travis-ci.org/mbierlee/poodinis) -Poodinis is a dependency injection framework for the D programming language. It is inspired by the [Spring Framework] and [Hypodermic] IoC container for C++. Poodinis supports registering and resolving classes either by concrete type or interface. Automatic injection of dependencies is supported through the use of UDAs (Referred to as autowiring). +Poodinis is a dependency injection framework for the D programming language. It is inspired by the [Spring Framework] and [Hypodermic] IoC container for C++. Poodinis supports registering and resolving classes either by concrete type or interface. Automatic injection of dependencies is supported through the use of UDAs or constructors. Requires at least a D 2.068.0 compatible compiler Uses the Phobos standard library @@ -59,7 +59,6 @@ Future Work ----------- * Component scan (auto-registration) * Phobos collections autowiring -* Constructor injection * Named qualifiers * Value type injection diff --git a/TUTORIAL.md b/TUTORIAL.md index a6363ea..4be8cd9 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -68,7 +68,9 @@ dependencies.register!ExampleClass.existingInstance(preExistingInstance); Autowiring ---------- -The real value of any dependency injection framework comes from its ability to autowire dependencies. Poodinis supports autowiring by simply applying the `@Autowire` UDA to a member of a class: +The real value of any dependency injection framework comes from its ability to automatically inject dependencies. Poodinis supports automatic injection either through autowiring members annotated with the `@Autowire` UDA or through constructor injection. +### UDA-based autowiring +UDA-based autowiring can be achieved by annotating members of a class with the `@Autowire` UDA: ```d class ExampleClassA {} @@ -79,8 +81,13 @@ class ExampleClassB { dependencies.register!ExampleClassA; auto exampleInstance = new ExampleClassB(); -dependencies.autowire(exampleInstance); -assert(exampleInstance.dependency !is null); + +// Manual autowiring +dependencies.autowire(exampleInstance); + +// Let the container handle injection +dependencies.register!ExampleClassB; +auto exampleInstance2 = dependencies.resolve!ExampleClassB; ``` It is possible to autowire public as well as protected and private members. @@ -104,6 +111,33 @@ class ExampleClass { } ``` +### Constructor injection +Poodinis also supports automatic injection of dependencies through constructors: +```d +class ExampleClassA {} + +class ExampleClassB { + private ExampleClassA dependency; + + this(ExampleClassA dependency) { + this.dependency = dependency; + } +} + +dependencies.register!ExampleClassA; +dependencies.register!ExampleClassB; + +auto instance = dependencies.resolve!ExampleClassB; + +``` +`ExampleClassA` is automatically resolved and passed to `ExampleClassB`'s constructor. +Classes with multiple constructors can be injected. The following rules apply to constructor injection: +* Injection is attempted at the order of declaration. However, this is compiler dependant and may not always be the case. +* Injection is attempted for the first constructor which has non-builtin types only in its parameter list. +* When a constructor with an empty parameter list is found, no other constructors are attempted (and nothing is injected). This can be used to explicitly prevent constructor injection. +* When no injectable constructor is found an InstanceCreationException will be thrown on resolve. +If the constructors of a class are not suitable for injection, you could manually configure its creation using Application Contexts (see chapter further down). + Circular dependencies --------------------- Poodinis can autowire circular dependencies when they are registered with `singleInstance` or `existingInstance` registration scopes. Circular dependencies in registrations with `newInstance` scopes will not be autowired, as this would cause an endless loop.