Add more future work

This commit is contained in:
Mike Bierlee 2014-06-08 17:40:21 +02:00
parent f123109a5e
commit 0a0ac1bba2

269
README.md
View file

@ -1,134 +1,135 @@
Poodinis Dependency Injection Framework Poodinis Dependency Injection Framework
======================================= =======================================
Version 0.1 Version 0.1
Copyright 2014 Mike bierlee Copyright 2014 Mike bierlee
Licensed under the terms of the MIT license - See [LICENSE.txt](LICENSE.txt) Licensed under the terms of the MIT license - See [LICENSE.txt](LICENSE.txt)
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 (Referred to as autowiring).
Uses D 2.065.0 and Phobos. Uses D 2.065.0 and Phobos.
History History
------- -------
For a full overview of changes, see [CHANGES.md](CHANGES.md) For a full overview of changes, see [CHANGES.md](CHANGES.md)
Getting started Getting started
--------------- ---------------
###DUB Dependency ###DUB Dependency
See the Poodinis [DUB project page] for instructions on how to include Poodinis into your project. See the Poodinis [DUB project page] for instructions on how to include Poodinis into your project.
###Quickstart ###Quickstart
The following example shows the typical usage of Poodinis: The following example shows the typical usage of Poodinis:
```d ```d
import poodinis.container; // The only import needed for now import poodinis.container; // The only import needed for now
interface Database{}; interface Database{};
class RelationalDatabase : Database {} class RelationalDatabase : Database {}
class DataWriter { class DataWriter {
@Autowire @Autowire
public Database database; // Automatically injected when class is resolved public Database database; // Automatically injected when class is resolved
} }
void main() { void main() {
auto container = Container.getInstance(); auto container = Container.getInstance();
container.register!DataWriter; container.register!DataWriter;
container.register!(Database, RelationalDatabase); container.register!(Database, RelationalDatabase);
auto writer = container.resolve!DataWriter; auto writer = container.resolve!DataWriter;
} }
``` ```
### The container ### 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 // Register a private container
auto container = new Container(); auto container = new Container();
// Or use the singleton container // Or use the singleton container
container = Container.getInstance(); container = Container.getInstance();
``` ```
###Registering dependencies ###Registering dependencies
They make dependencies available, they have to be registered: They make dependencies available, they have to be registered:
```d ```d
// Register concrete class // Register concrete class
container.register!ExampleClass; container.register!ExampleClass;
// Register by interface // Register by interface
container.register!(ExampleInterface, ExampleClass); container.register!(ExampleInterface, ExampleClass);
``` ```
In the above example, dependencies on the concrete class and interface will resolve an instance of class ExampleClass. Registering a class by interface does not automatically register by concrete type. In the above example, dependencies on the concrete class and interface will resolve an instance of class ExampleClass. Registering a class by interface does not automatically register by concrete type.
###Resolving dependencies ###Resolving dependencies
To manually resolve a dependency, all you have to do is resolve the dependency's type using the container in which it is registered: To manually resolve a dependency, all you have to do is resolve the dependency's type using the container in which it is registered:
```d ```d
auto exampleClassInstance = container.resolve!ExampleClass; auto exampleClassInstance = container.resolve!ExampleClass;
``` ```
If the class is registered by interface and not by concrete type, you cannot resolve the class by concrete type. Registration of both a concrete type and interface type will resolve different registrations, returning different instances: If the class is registered by interface and not by concrete type, you cannot resolve the class by concrete type. Registration of both a concrete type and interface type will resolve different registrations, returning different instances:
```d ```d
auto exampleClassInstance = container.resolve!ExampleClass; auto exampleClassInstance = container.resolve!ExampleClass;
auto exampleClassInstance2 = container.resolve!ExampleInterface; auto exampleClassInstance2 = container.resolve!ExampleInterface;
assert(exampleClassInstance !is exampleClassInstance2); assert(exampleClassInstance !is exampleClassInstance2);
``` ```
###Dependency scopes ###Dependency scopes
With dependency scopes, you can control how a dependency is resolved. The scope determines which instance is returned, be it the same each time or a new one. The following scopes are available: With dependency scopes, you can control how a dependency is resolved. The scope determines which instance is returned, be it the same each time or a new one. The following scopes are available:
* Resolve a dependency using a single instance (default): * Resolve a dependency using a single instance (default):
```d ```d
container.register!(ExampleClass).singleInstance(); container.register!(ExampleClass).singleInstance();
``` ```
* Resolve a dependency with a new instance each time it is resolved: * Resolve a dependency with a new instance each time it is resolved:
```d ```d
container.register!(ExampleClass).newInstance(); container.register!(ExampleClass).newInstance();
``` ```
* Resolve a dependency using a pre-existing instance * Resolve a dependency using a pre-existing instance
```d ```d
auto preExistingInstance = new ExampleClass(); auto preExistingInstance = new ExampleClass();
container.register!(ExampleClass).existingInstance(preExistingInstance); container.register!(ExampleClass).existingInstance(preExistingInstance);
``` ```
###Autowiring ###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 autowire dependencies. Poodinis supports autowiring by simply applying the **@Autowire** UDA to a member of a class:
```d ```d
class ExampleClassA {} class ExampleClassA {}
class ExampleClassB { class ExampleClassB {
@Autowire @Autowire
public ExampleClassA dependency; public ExampleClassA dependency;
} }
container.register!ExampleClassA; container.register!ExampleClassA;
auto exampleInstance = new ExampleClassB(); auto exampleInstance = new ExampleClassB();
container.autowire!ExampleClassB(exampleInstance); container.autowire!ExampleClassB(exampleInstance);
assert(exampleInstance.dependency !is null); assert(exampleInstance.dependency !is null);
``` ```
At the moment, it is only possible to autowire public members or properties. At the moment, it is only possible to autowire public members or properties.
Dependencies are automatically autowired when a class is resolved. So when you register ExampleClassB, its member, *dependency*, is automatically injected: Dependencies are automatically autowired when a class is resolved. So when you register ExampleClassB, its member, *dependency*, is automatically injected:
```d ```d
container.register!ExampleClassA; container.register!ExampleClassA;
container.register!ExampleClassB; container.register!ExampleClassB;
auto instance = container.resolve!ExampleClassB; auto instance = container.resolve!ExampleClassB;
assert(instance.dependency !is null); assert(instance.dependency !is null);
``` ```
If an interface is to be autowired, you must register a concrete class by interface. Any class registered by concrete type can only be injected when a dependency on a concrete type is autowired. If an interface is to be autowired, you must register a concrete class by interface. Any class registered by concrete type can only be injected when a dependency on a concrete type is autowired.
###Circular dependencies ###Circular dependencies
Poodinis can autowire circular dependencies when they are registered with singleInstance or existingInstance registration scopes. See Known issues for the limitations on newInstance scopes. Poodinis can autowire circular dependencies when they are registered with singleInstance or existingInstance registration scopes. See Known issues for the limitations on newInstance scopes.
Known issues Known issues
------------ ------------
* Due to preventive measures of recursion issues in circular dependencies, registrations which are supposed to yield new instances will not autowire classes for which a circular dependency is detected. A new instance will be resolved but the instance's members will not be autowired. * Due to preventive measures of recursion issues in circular dependencies, registrations which are supposed to yield new instances will not autowire classes for which a circular dependency is detected. A new instance will be resolved but the instance's members will not be autowired.
Future Work Future Work
----------- -----------
* Thread safety * Thread safety
* Component scan (auto-registration) * Component scan (auto-registration)
* Registering multiple concrete classes to the same interface
[Spring Framework]: http://projects.spring.io/spring-framework/
[Hypodermic]: https://code.google.com/p/hypodermic/ [Spring Framework]: http://projects.spring.io/spring-framework/
[DUB]: http://code.dlang.org/ [Hypodermic]: https://code.google.com/p/hypodermic/
[DUB project page]: http://code.dlang.org/packages/poodinis [DUB]: http://code.dlang.org/
[DUB project page]: http://code.dlang.org/packages/poodinis