Move context registration related method out of container

Should be still usable as before because of UFCS
This commit is contained in:
Mike Bierlee 2016-12-14 21:49:56 +01:00
parent 68c8d6b6a6
commit 7ba8e545f6
4 changed files with 128 additions and 126 deletions

View file

@ -384,21 +384,6 @@ synchronized class DependencyContainer {
registrations.remove(typeid(RegistrationType));
}
/**
* Register dependencies through an application context.
*
* An application context allows you to fine-tune dependency set-up and instantiation.
* It is mostly used for dependencies which come from an external library or when you don't
* want to use annotations to set-up dependencies in your classes.
*/
public void registerContext(Context : ApplicationContext)() {
auto context = new Context();
context.registerDependencies(this);
context.registerContextComponents(this);
this.register!(ApplicationContext, Context)().existingInstance(context);
autowire(this, context);
}
/**
* Returns a global singleton instance of a dependency container.
* Deprecated: create new instance with new keyword or implement your own singleton factory (method)

View file

@ -17,6 +17,7 @@ import poodinis.container;
import poodinis.registration;
import poodinis.factory;
import poodinis.polyfill;
import poodinis.autowire;
import std.traits;
@ -44,6 +45,21 @@ struct RegisterByType(Type) {
*/
struct Prototype {}
/**
* Register dependencies through an application context.
*
* An application context allows you to fine-tune dependency set-up and instantiation.
* It is mostly used for dependencies which come from an external library or when you don't
* want to use annotations to set-up dependencies in your classes.
*/
public void registerContext(Context : ApplicationContext)(shared(DependencyContainer) container) {
auto context = new Context();
context.registerDependencies(container);
context.registerContextComponents(container);
container.register!(ApplicationContext, Context)().existingInstance(context);
autowire(container, context);
}
public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) {
foreach (member ; __traits(allMembers, ApplicationContextType)) {
static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) {

View file

@ -12,52 +12,6 @@ import std.exception;
import core.thread;
version(unittest) {
class TestContext : ApplicationContext {
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!TestClass;
}
@Component
public UnrelatedClass unrelated() {
return new UnrelatedClass();
}
}
class AutowiredTestContext : ApplicationContext {
@Autowire
private UnrelatedClass unrelatedClass;
@Component
public ClassWrapper wrapper() {
return new ClassWrapper(unrelatedClass);
}
}
class ComplexAutowiredTestContext : ApplicationContext {
@Autowire
private UnrelatedClass unrelatedClass;
@Autowire
protected ClassWrapper classWrapper;
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!UnrelatedClass;
}
@Component
public ClassWrapper wrapper() {
return new ClassWrapper(unrelatedClass);
}
@Component
public ClassWrapperWrapper wrapperWrapper() {
return new ClassWrapperWrapper(classWrapper);
}
}
interface TestInterface {
}
@ -165,22 +119,6 @@ version(unittest) {
public Wants wants;
}
class ClassWrapper {
public Object someClass;
this(Object someClass) {
this.someClass = someClass;
}
}
class ClassWrapperWrapper {
public ClassWrapper wrapper;
this(ClassWrapper wrapper) {
this.wrapper = wrapper;
}
}
class Cocktail {
@Autowire
public Moolah moolah;
@ -588,55 +526,6 @@ version(unittest) {
assert(instance.unrelated !is null);
}
// Test setting up simple dependencies through application context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!TestContext;
auto instance = container.resolve!TestClass;
assert(instance !is null);
}
// Test resolving dependency from registered application context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!TestContext;
auto instance = container.resolve!UnrelatedClass;
assert(instance !is null);
}
// Test autowiring application context
unittest {
auto container = new shared DependencyContainer();
container.register!UnrelatedClass;
container.registerContext!AutowiredTestContext;
auto instance = container.resolve!ClassWrapper;
assert(instance !is null);
assert(instance.someClass !is null);
}
// Test autowiring application context with dependencies registered in same context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!ComplexAutowiredTestContext;
auto instance = container.resolve!ClassWrapperWrapper;
auto wrapper = container.resolve!ClassWrapper;
auto someClass = container.resolve!UnrelatedClass;
assert(instance !is null);
assert(instance.wrapper is wrapper);
assert(instance.wrapper.someClass is someClass);
}
// Test resolving registered context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!TestContext;
container.resolve!ApplicationContext;
}
// Test set persistent registration options
unittest {
auto container = new shared DependencyContainer();

View file

@ -49,6 +49,70 @@ version(unittest) {
class PieChart {}
class CakeChart : PieChart {}
class ClassWrapper {
public Object someClass;
this(Object someClass) {
this.someClass = someClass;
}
}
class ClassWrapperWrapper {
public ClassWrapper wrapper;
this(ClassWrapper wrapper) {
this.wrapper = wrapper;
}
}
class SimpleContext : ApplicationContext {
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!CakeChart;
}
@Component
public Apple apple() {
return new Apple();
}
}
class ComplexAutowiredTestContext : ApplicationContext {
@Autowire
private Apple apple;
@Autowire
protected ClassWrapper classWrapper;
public override void registerDependencies(shared(DependencyContainer) container) {
container.register!Apple;
}
@Component
public ClassWrapper wrapper() {
return new ClassWrapper(apple);
}
@Component
public ClassWrapperWrapper wrapperWrapper() {
return new ClassWrapperWrapper(classWrapper);
}
}
class AutowiredTestContext : ApplicationContext {
@Autowire
private Apple apple;
@Component
public ClassWrapper wrapper() {
return new ClassWrapper(apple);
}
}
class TestContext : ApplicationContext {
@Component
@ -138,4 +202,52 @@ version(unittest) {
assert(firstInstance !is secondInstance);
}
// Test setting up simple dependencies through application context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!SimpleContext;
auto instance = container.resolve!CakeChart;
assert(instance !is null);
}
// Test resolving dependency from registered application context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!SimpleContext;
auto instance = container.resolve!Apple;
assert(instance !is null);
}
// Test autowiring application context
unittest {
auto container = new shared DependencyContainer();
container.register!Apple;
container.registerContext!AutowiredTestContext;
auto instance = container.resolve!ClassWrapper;
assert(instance !is null);
assert(instance.someClass !is null);
}
// Test autowiring application context with dependencies registered in same context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!ComplexAutowiredTestContext;
auto instance = container.resolve!ClassWrapperWrapper;
auto wrapper = container.resolve!ClassWrapper;
auto someClass = container.resolve!Apple;
assert(instance !is null);
assert(instance.wrapper is wrapper);
assert(instance.wrapper.someClass is someClass);
}
// Test resolving registered context
unittest {
auto container = new shared DependencyContainer();
container.registerContext!TestContext;
container.resolve!ApplicationContext;
}
}