mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Add more future work
This commit is contained in:
parent
f123109a5e
commit
0a0ac1bba2
269
README.md
269
README.md
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue