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
|
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**
|
**Version 8.1.0-beta.2**
|
||||||
* FIX inheritance type template in custom instance creator (PR #29)
|
* 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:
|
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):
|
* Resolve a dependency using a single instance (default):
|
||||||
|
|
||||||
```d
|
```d
|
||||||
dependencies.register!ExampleClass.singleInstance();
|
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
|
```d
|
||||||
dependencies.register!ExampleClass.newInstance();
|
dependencies.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();
|
||||||
dependencies.register!ExampleClass.existingInstance(preExistingInstance);
|
dependencies.register!ExampleClass.existingInstance(preExistingInstance);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* Resolve a dependency using a custom initializer delegate:
|
||||||
|
```d
|
||||||
|
dependencies.register!ExampleClass.initializedBy({
|
||||||
|
return new ExampleClass();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Automatic Injection
|
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.
|
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()
|
void main()
|
||||||
{
|
{
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto dependencies = new shared DependencyContainer();
|
||||||
dependencies.register!Doohickey({
|
dependencies.register!Doohickey.initializedBy({
|
||||||
writeln("Creating Doohickey via initializer delegate.");
|
writeln("Creating Doohickey via initializer delegate.");
|
||||||
return new Doohickey();
|
return new Doohickey();
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,8 +30,6 @@ debug {
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
}
|
}
|
||||||
|
|
||||||
alias InjectionInitializer(T) = T delegate();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when errors occur while resolving a type in a dependency container.
|
* 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);
|
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.
|
* Register a dependency by super type.
|
||||||
*
|
*
|
||||||
|
@ -201,45 +194,6 @@ synchronized class DependencyContainer {
|
||||||
return newRegistration;
|
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) {
|
private bool hasOption(OptionType)(OptionType options, OptionType persistentOptions, OptionType option) {
|
||||||
return ((options | persistentOptions) & option) != 0;
|
return ((options | persistentOptions) & option) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,17 @@ public Registration existingInstance(Registration registration, Object instance)
|
||||||
return registration;
|
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) {
|
public string toConcreteTypeListString(Registration[] registrations) {
|
||||||
auto concreteTypeListString = "";
|
auto concreteTypeListString = "";
|
||||||
foreach (registration ; registrations) {
|
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");
|
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
|
// Test autowire resolved instances
|
||||||
unittest {
|
unittest {
|
||||||
auto container = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
|
|
Loading…
Reference in a new issue