mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Move injection initializer to registration scope
This commit is contained in:
parent
89512e0cb0
commit
8f4a64cf4c
|
@ -1,5 +1,8 @@
|
|||
Poodinis Changelog
|
||||
==================
|
||||
**Version 8.1.0-beta.3**
|
||||
* CHANGE injection initializers to be defined as a registration scope instead of via Container.register(). See initializedBy().
|
||||
|
||||
**Version 8.1.0-beta.2**
|
||||
* FIX inheritance type template in custom instance creator (PR #29)
|
||||
|
||||
|
|
12
TUTORIAL.md
12
TUTORIAL.md
|
@ -50,22 +50,28 @@ Dependency Creation Behaviour
|
|||
You can control how a dependency is resolved by specifying a creation scope during registration. 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):
|
||||
|
||||
```d
|
||||
dependencies.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
|
||||
dependencies.register!ExampleClass.newInstance();
|
||||
```
|
||||
* Resolve a dependency using a pre-existing instance
|
||||
|
||||
* Resolve a dependency using a pre-existing instance:
|
||||
```d
|
||||
auto preExistingInstance = new ExampleClass();
|
||||
dependencies.register!ExampleClass.existingInstance(preExistingInstance);
|
||||
```
|
||||
|
||||
* Resolve a dependency using a custom initializer delegate:
|
||||
```d
|
||||
dependencies.register!ExampleClass.initializedBy({
|
||||
return new ExampleClass();
|
||||
});
|
||||
```
|
||||
|
||||
Automatic Injection
|
||||
----------
|
||||
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.
|
||||
|
|
|
@ -15,7 +15,7 @@ class Doohickey
|
|||
void main()
|
||||
{
|
||||
auto dependencies = new shared DependencyContainer();
|
||||
dependencies.register!Doohickey({
|
||||
dependencies.register!Doohickey.initializedBy({
|
||||
writeln("Creating Doohickey via initializer delegate.");
|
||||
return new Doohickey();
|
||||
});
|
||||
|
|
|
@ -30,8 +30,6 @@ debug {
|
|||
import std.stdio;
|
||||
}
|
||||
|
||||
alias InjectionInitializer(T) = T delegate();
|
||||
|
||||
/**
|
||||
* Exception thrown when errors occur while resolving a type in a dependency container.
|
||||
*/
|
||||
|
@ -149,11 +147,6 @@ synchronized class DependencyContainer {
|
|||
return register!(ConcreteType, ConcreteType)(options);
|
||||
}
|
||||
|
||||
Registration register(ConcreteType)(InjectionInitializer!ConcreteType initializer,
|
||||
RegistrationOption options = RegistrationOption.none) {
|
||||
return register!(ConcreteType, ConcreteType)(initializer, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a dependency by super type.
|
||||
*
|
||||
|
@ -201,45 +194,6 @@ synchronized class DependencyContainer {
|
|||
return newRegistration;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Deduplicate code
|
||||
*/
|
||||
Registration register(SuperType, ConcreteType : SuperType)(InjectionInitializer!SuperType initializer,
|
||||
RegistrationOption options = RegistrationOption.none)
|
||||
if (is(ConcreteType == class)) {
|
||||
|
||||
TypeInfo registeredType = typeid(SuperType);
|
||||
TypeInfo_Class concreteType = typeid(ConcreteType);
|
||||
|
||||
debug(poodinisVerbose) {
|
||||
writeln(format("DEBUG: Register type %s (as %s)", concreteType.toString(), registeredType.toString()));
|
||||
}
|
||||
|
||||
auto existingRegistration = getExistingRegistration(registeredType, concreteType);
|
||||
if (existingRegistration) {
|
||||
return existingRegistration;
|
||||
}
|
||||
|
||||
InstanceFactory instanceFactory = new class InstanceFactory {
|
||||
protected override Object createInstance() {
|
||||
return cast(Object)initializer();
|
||||
}
|
||||
};
|
||||
|
||||
auto newRegistration = new AutowiredRegistration!ConcreteType(registeredType, instanceFactory, this);
|
||||
newRegistration.singleInstance();
|
||||
|
||||
static if (!is(SuperType == ConcreteType)) {
|
||||
if (!hasOption(options, persistentRegistrationOptions, RegistrationOption.doNotAddConcreteTypeRegistration)) {
|
||||
auto concreteTypeRegistration = register!ConcreteType;
|
||||
concreteTypeRegistration.linkTo(newRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
registrations[registeredType] ~= cast(shared(Registration)) newRegistration;
|
||||
return newRegistration;
|
||||
}
|
||||
|
||||
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
||||
return ((options | persistentOptions) & option) != 0;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,17 @@ public Registration existingInstance(Registration registration, Object instance)
|
|||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scopes registrations to create 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();
|
||||
});
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
public string toConcreteTypeListString(Registration[] registrations) {
|
||||
auto concreteTypeListString = "";
|
||||
foreach (registration ; registrations) {
|
||||
|
|
|
@ -80,6 +80,17 @@ version(unittest) {
|
|||
assert(expectedInstance is actualInstance, "Resolved instance from existing instance scope is not the same as the registered instance");
|
||||
}
|
||||
|
||||
// Test creating instance via customer initializer on resolve
|
||||
unittest {
|
||||
auto container = new shared DependencyContainer();
|
||||
auto expectedInstance = new TestClass();
|
||||
container.register!TestClass.initializedBy({
|
||||
return expectedInstance;
|
||||
});
|
||||
auto actualInstance = container.resolve!TestClass;
|
||||
assert(expectedInstance is actualInstance, "Resolved instance does not come from the custom initializer");
|
||||
}
|
||||
|
||||
// Test autowire resolved instances
|
||||
unittest {
|
||||
auto container = new shared DependencyContainer();
|
||||
|
|
Loading…
Reference in a new issue