mirror of
https://github.com/mbierlee/poodinis.git
synced 2024-11-15 04:04:01 +01:00
Merge branch 'feature/autowire-private-fields' of https://github.com/Extrawurst/poodinis into Extrawurst-feature/autowire-private-fields
Conflicts: README.md
This commit is contained in:
commit
d87c8a0457
|
@ -31,7 +31,7 @@ class RelationalDatabase : Database {}
|
||||||
|
|
||||||
class DataWriter {
|
class DataWriter {
|
||||||
@Autowire
|
@Autowire
|
||||||
public Database database; // Automatically injected when class is resolved
|
private Database database; // Automatically injected when class is resolved
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ExampleClassA {}
|
||||||
|
|
||||||
class ExampleClassB {
|
class ExampleClassB {
|
||||||
@Autowire
|
@Autowire
|
||||||
public ExampleClassA dependency;
|
private ExampleClassA dependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies.register!ExampleClassA;
|
dependencies.register!ExampleClassA;
|
||||||
|
@ -83,7 +83,7 @@ auto exampleInstance = new ExampleClassB();
|
||||||
dependencies.autowire(exampleInstance);
|
dependencies.autowire(exampleInstance);
|
||||||
assert(exampleInstance.dependency !is null);
|
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:
|
Dependencies are automatically autowired when a class is resolved. So when you register ExampleClassB, its member, *dependency*, is automatically autowired:
|
||||||
```d
|
```d
|
||||||
|
|
|
@ -101,8 +101,8 @@ public void autowire(Type)(shared(DependencyContainer) container, Type instance)
|
||||||
printDebugAutowiredInstance(typeid(Type), &instance);
|
printDebugAutowiredInstance(typeid(Type), &instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (member ; __traits(allMembers, Type)) {
|
foreach(idx, name; FieldNameTuple!Type) {
|
||||||
autowireMember!member(container, instance);
|
autowireMember!(name, idx, Type)(container, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,19 +114,18 @@ 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));
|
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) {
|
private void autowireMember(string member, size_t tupleIdx, 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, Type.tupleof[tupleIdx])) {
|
||||||
foreach(autowireAttribute; __traits(getAttributes, __traits(getMember, instance, member))) {
|
|
||||||
static if (__traits(isSame, autowireAttribute, Autowire) || is(autowireAttribute == Autowire!T, T)) {
|
static if (__traits(isSame, autowireAttribute, Autowire) || is(autowireAttribute == Autowire!T, T)) {
|
||||||
if (__traits(getMember, instance, member) is null) {
|
if (instance.tupleof[tupleIdx] is null) {
|
||||||
alias MemberType = typeof(__traits(getMember, instance, member));
|
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) {
|
static if (isDynamicArray!MemberType) {
|
||||||
alias MemberElementType = ElementType!MemberType;
|
alias MemberElementType = ElementType!MemberType;
|
||||||
auto instances = container.resolveAll!MemberElementType;
|
auto instances = container.resolveAll!MemberElementType;
|
||||||
__traits(getMember, instance, member) = instances;
|
instance.tupleof[tupleIdx] = instances;
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
printDebugAutowiringArray(typeid(MemberElementType), typeid(Type), &instance, member);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +145,7 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
|
||||||
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container);
|
qualifiedInstance = createOrResolveInstance!(MemberType, MemberType, assignNewInstance)(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
__traits(getMember, instance, member) = qualifiedInstance;
|
instance.tupleof[tupleIdx] = qualifiedInstance;
|
||||||
|
|
||||||
debug(poodinisVerbose) {
|
debug(poodinisVerbose) {
|
||||||
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
printDebugAutowiringCandidate(qualifiedInstanceType, &qualifiedInstance, typeid(Type), &instance, member);
|
||||||
|
@ -158,7 +157,6 @@ private void autowireMember(string member, Type)(shared(DependencyContainer) con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew)(shared(DependencyContainer) container) {
|
private QualifierType createOrResolveInstance(MemberType, QualifierType, bool createNew)(shared(DependencyContainer) container) {
|
||||||
static if (createNew) {
|
static if (createNew) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ version(unittest) {
|
||||||
|
|
||||||
class ComponentD {
|
class ComponentD {
|
||||||
public @Autowire InterfaceA componentC = null;
|
public @Autowire InterfaceA componentC = null;
|
||||||
|
private @Autowire InterfaceA privateComponentC = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyAttribute{};
|
class DummyAttribute{};
|
||||||
|
@ -87,6 +88,15 @@ version(unittest) {
|
||||||
assert(componentD.componentC !is null, "Autowirable dependency failed to autowire");
|
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
|
// Test autowiring will only happen once
|
||||||
unittest {
|
unittest {
|
||||||
shared(DependencyContainer) container = new DependencyContainer();
|
shared(DependencyContainer) container = new DependencyContainer();
|
||||||
|
|
Loading…
Reference in a new issue