2016-01-06 20:28:25 +01:00
|
|
|
/**
|
|
|
|
* Contains the implementation of application context setup.
|
|
|
|
*
|
|
|
|
* Part of the Poodinis Dependency Injection framework.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Mike Bierlee, m.bierlee@lostmoment.com
|
|
|
|
* Copyright: 2014-2016 Mike Bierlee
|
|
|
|
* License:
|
|
|
|
* This software is licensed under the terms of the MIT license.
|
|
|
|
* The full terms of the license can be found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
module poodinis.context;
|
|
|
|
|
|
|
|
import poodinis.container;
|
|
|
|
import poodinis.registration;
|
2016-08-17 20:44:36 +02:00
|
|
|
import poodinis.factory;
|
2016-01-06 20:28:25 +01:00
|
|
|
|
|
|
|
import std.traits;
|
|
|
|
|
|
|
|
class ApplicationContext {
|
|
|
|
public void registerDependencies(shared(DependencyContainer) container) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A component annotation is used for specifying which factory methods produce components in
|
|
|
|
* an application context.
|
|
|
|
*/
|
|
|
|
struct Component {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This annotation allows you to specify by which super type the component should be registered. This
|
|
|
|
* enables you to use type-qualified alternatives for dependencies.
|
|
|
|
*/
|
|
|
|
struct RegisterByType(Type) {
|
|
|
|
Type type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-08-17 22:37:02 +02:00
|
|
|
* Components with the prototype registration will be scoped as dependencies which will create
|
2016-01-06 20:28:25 +01:00
|
|
|
* new instances every time they are resolved. The factory method will be called repeatedly.
|
|
|
|
*/
|
|
|
|
struct Prototype {}
|
|
|
|
|
|
|
|
public void registerContextComponents(ApplicationContextType : ApplicationContext)(ApplicationContextType context, shared(DependencyContainer) container) {
|
|
|
|
foreach (member ; __traits(allMembers, ApplicationContextType)) {
|
2016-02-09 21:02:56 +01:00
|
|
|
static if (__traits(getProtection, __traits(getMember, context, member)) == "public" && hasUDA!(__traits(getMember, context, member), Component)) {
|
2016-01-06 20:28:25 +01:00
|
|
|
auto factoryMethod = &__traits(getMember, context, member);
|
|
|
|
Registration registration = null;
|
|
|
|
auto createsSingleton = CreatesSingleton.yes;
|
|
|
|
|
|
|
|
foreach(attribute; __traits(getAttributes, __traits(getMember, context, member))) {
|
|
|
|
static if (is(attribute == RegisterByType!T, T)) {
|
|
|
|
registration = container.register!(typeof(attribute.type), ReturnType!factoryMethod);
|
|
|
|
} else static if (__traits(isSame, attribute, Prototype)) {
|
|
|
|
createsSingleton = CreatesSingleton.no;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (registration is null) {
|
|
|
|
registration = container.register!(ReturnType!factoryMethod);
|
|
|
|
}
|
|
|
|
|
2016-08-17 23:01:22 +02:00
|
|
|
registration.instanceFactory.factoryParameters = InstanceFactoryParameters(registration.instanceType, createsSingleton, null, factoryMethod);
|
2016-01-06 20:28:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|