mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
allow autowiring private fields too
This commit is contained in:
parent
7d206e8964
commit
7d2ba1bef9
|
@ -31,7 +31,7 @@ class RelationalDatabase : Database {}
|
|||
|
||||
class DataWriter {
|
||||
@Autowire
|
||||
public Database database; // Automatically injected when class is resolved
|
||||
private Database database; // Automatically injected when class is resolved
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
|
|
@ -70,7 +70,7 @@ class ExampleClassA {}
|
|||
|
||||
class ExampleClassB {
|
||||
@Autowire
|
||||
public ExampleClassA dependency;
|
||||
private ExampleClassA dependency;
|
||||
}
|
||||
|
||||
dependencies.register!ExampleClassA;
|
||||
|
@ -78,7 +78,7 @@ auto exampleInstance = new ExampleClassB();
|
|||
dependencies.autowire(exampleInstance);
|
||||
assert(exampleInstance.dependency !is null);
|
||||
```
|
||||
At the moment, it is only possible to autowire public members or properties.
|
||||
It is possible to autowire public and private members.
|
||||
|
||||
Dependencies are automatically autowired when a class is resolved. So when you register ExampleClassB, its member, *dependency*, is automatically autowired:
|
||||
```d
|
||||
|
|
|
@ -101,8 +101,8 @@ public void autowire(Type)(shared(DependencyContainer) container, Type instance)
|
|||
printDebugAutowiredInstance(typeid(Type), &instance);
|
||||
}
|
||||
|
||||
foreach (member ; __traits(allMembers, Type)) {
|
||||
autowireMember!member(container, instance);
|
||||
foreach(idx, name; FieldNameTuple!Type) {
|
||||
autowireMember!(name, idx, Type)(container, instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,48 +114,46 @@ private void printDebugAutowiringArray(TypeInfo superTypeInfo, TypeInfo instance
|
|||
writeln(format("DEBUG: Autowired all registered instances of super type %s to [%s@%s].%s", superTypeInfo, instanceType, instanceAddress, member));
|
||||
}
|
||||
|
||||
private void autowireMember(string member, Type)(shared(DependencyContainer) container, Type instance) {
|
||||
static if(__traits(compiles, __traits(getMember, instance, member)) && __traits(compiles, __traits(getAttributes, __traits(getMember, instance, member)))) {
|
||||
foreach(autowireAttribute; __traits(getAttributes, __traits(getMember, instance, member))) {
|
||||
static if (__traits(isSame, autowireAttribute, Autowire) || is(autowireAttribute == Autowire!T, T)) {
|
||||
if (__traits(getMember, instance, member) is null) {
|
||||
alias MemberType = typeof(__traits(getMember, instance, member));
|
||||
private void autowireMember(string member, size_t tupleIdx, Type)(shared(DependencyContainer) container, Type instance) {
|
||||
foreach(autowireAttribute; __traits(getAttributes, Type.tupleof[tupleIdx])) {
|
||||
static if (__traits(isSame, autowireAttribute, Autowire) || is(autowireAttribute == Autowire!T, T)) {
|
||||
if (instance.tupleof[tupleIdx] is null) {
|
||||
alias MemberType = typeof(Type.tupleof[tupleIdx]);
|
||||
|
||||
enum assignNewInstance = hasUDA!(__traits(getMember, instance, member), AssignNewInstance);
|
||||
enum assignNewInstance = hasUDA!(Type.tupleof[tupleIdx], AssignNewInstance);
|
||||
|
||||
static if (isDynamicArray!MemberType) {
|
||||
alias MemberElementType = ElementType!MemberType;
|
||||
auto instances = container.resolveAll!MemberElementType;
|
||||
__traits(getMember, instance, member) = instances;
|
||||
static if (isDynamicArray!MemberType) {
|
||||
alias MemberElementType = ElementType!MemberType;
|
||||
auto instances = container.resolveAll!MemberElementType;
|
||||
instance.tupleof[tupleIdx] = instances;
|
||||
debug(poodinisVerbose) {
|
||||
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
||||
}
|
||||
} else {
|
||||
debug(poodinisVerbose) {
|
||||
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
||||
}
|
||||
|
||||
MemberType qualifiedInstance;
|
||||
static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) {
|
||||
alias QualifierType = typeof(autowireAttribute.qualifier);
|
||||
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance)(container);
|
||||
debug(poodinisVerbose) {
|
||||
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
||||
qualifiedInstanceType = typeid(QualifierType);
|
||||
}
|
||||
} else {
|
||||
debug(poodinisVerbose) {
|
||||
TypeInfo qualifiedInstanceType = typeid(MemberType);
|
||||
}
|
||||
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container);
|
||||
}
|
||||
|
||||
MemberType qualifiedInstance;
|
||||
static if (is(autowireAttribute == Autowire!T, T) && !is(autowireAttribute.qualifier == UseMemberType)) {
|
||||
alias QualifierType = typeof(autowireAttribute.qualifier);
|
||||
qualifiedInstance = createOrResolveInstance!(MemberType, QualifierType, assignNewInstance)(container);
|
||||
debug(poodinisVerbose) {
|
||||
qualifiedInstanceType = typeid(QualifierType);
|
||||
}
|
||||
} else {
|
||||
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container);
|
||||
}
|
||||
instance.tupleof[tupleIdx] = qualifiedInstance;
|
||||
|
||||
__traits(getMember, instance, member) = qualifiedInstance;
|
||||
|
||||
debug(poodinisVerbose) {
|
||||
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
||||
}
|
||||
debug(poodinisVerbose) {
|
||||
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ version(unittest) {
|
|||
|
||||
class ComponentD {
|
||||
public @Autowire InterfaceA componentC = null;
|
||||
private @Autowire InterfaceA privateComponentC = null;
|
||||
}
|
||||
|
||||
class DummyAttribute{};
|
||||
|
@ -87,6 +88,15 @@ version(unittest) {
|
|||
assert(componentD.componentC !is null, "Autowirable dependency failed to autowire");
|
||||
}
|
||||
|
||||
// Test autowiring private members
|
||||
unittest {
|
||||
shared(DependencyContainer) container = new DependencyContainer();
|
||||
container.register!(InterfaceA, ComponentC);
|
||||
auto componentD = new ComponentD();
|
||||
container.autowire!(ComponentD)(componentD);
|
||||
assert(componentD.privateComponentC is componentD.componentC, "Autowire private dependency failed");
|
||||
}
|
||||
|
||||
// Test autowiring will only happen once
|
||||
unittest {
|
||||
shared(DependencyContainer) container = new DependencyContainer();
|
||||
|
|
Loading…
Reference in a new issue