Add ability to assign new instance to autowired member regardless of registration scope

This commit is contained in:
Mike Bierlee 2015-07-03 23:45:10 +02:00
parent 1551f9e012
commit 3e11ff1e92
2 changed files with 46 additions and 2 deletions

View file

@ -64,6 +64,21 @@ struct Autowire(QualifierType = UseMemberType) {
QualifierType qualifier;
};
/**
* UDA for annotating class members to be autowired with a new instance regardless of their registration scope.
*
* Examples:
*---
* class Car {
* @Autowire
* @AssignNewInstance
* public Antenna antenna;
* }
*---
* antenna will always be assigned a new instance of class Antenna.
*/
struct AssignNewInstance {}
private void printDebugAutowiredInstance(TypeInfo instanceType, void* instanceAddress) {
writeln(format("DEBUG: Autowiring members of [%s@%s]", instanceType, instanceAddress));
}
@ -105,6 +120,8 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
if (__traits(getMember, instance, member) is null) {
alias MemberType = typeof(__traits(getMember, instance, member));
enum assignNewInstance = hasUDA!(__traits(getMember, instance, member), AssignNewInstance);
static if (isDynamicArray!MemberType) {
alias MemberElementType = ElementType!MemberType;
auto instances = container.resolveAll!MemberElementType;
@ -120,12 +137,12 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
MemberType qualifiedInstance;
static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) {
alias QualifierType = typeof(autowireAttribute.qualifier);
qualifiedInstance = container.resolve!(MemberType, QualifierType);
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance)(container);
debug(poodinisVerbose) {
qualifiedInstanceType = typeid(QualifierType);
}
} else {
qualifiedInstance = container.resolve!(MemberType);
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container);
}
__traits(getMember, instance, member) = qualifiedInstance;
@ -142,6 +159,15 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
}
}
private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew)(shared(DependencyContainer) container) {
static if (createNew) {
auto instanceFactory = new NewInstanceScope(typeid(MemberType));
return cast(MemberType) instanceFactory.getInstance();
} else {
return container.resolve!(MemberType, QualifierType);
}
}
/**
* Autowire the given instance using the globally available dependency container.
*

View file

@ -63,6 +63,11 @@ version(unittest) {
@Autowire
public InterfaceA[] components;
}
class ComponentCharlie {
@Autowire
@AssignNewInstance
public ComponentA componentA;
}
// Test autowiring concrete type to existing instance
unittest {
@ -170,4 +175,17 @@ version(unittest) {
assert(lord.components.length == 2, "Dynamic array was not autowired");
}
// Test autowiring new instance of singleinstance registration with newInstance UDA
unittest {
shared(DependencyContainer) container = new DependencyContainer();
container.register!ComponentA;
auto regularComponentA = container.resolve!ComponentA;
auto charlie = new ComponentCharlie();
container.autowire(charlie);
assert(charlie.componentA !is regularComponentA, "Autowiring class with AssignNewInstance did not yield a different instance");
}
}