1 // Copyright Orfeo Da Viá 2014. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module endovena.provider; 7 8 import std.string : chomp; 9 import std.traits; 10 11 import endovena.container; 12 13 interface Provider { 14 Object get(); 15 } 16 17 class ClassProvider(T): Provider { 18 private Container container; 19 this(Container container) { 20 this.container = container; 21 } 22 23 Object get() { 24 return create!T(container); 25 } 26 } 27 28 class FunctionProvider: Provider { 29 private Object delegate() provide; 30 31 this(Object delegate() provide) { 32 this.provide = provide; 33 } 34 35 Object get() { 36 return this.provide(); 37 } 38 } 39 40 class FactoryProvider: Provider { 41 private Container container; 42 private Object delegate(Container) provide; 43 this(Container container, Object delegate(Container) provide) { 44 this.container = container; 45 this.provide = provide; 46 } 47 48 Object get() { 49 return this.provide(container); 50 } 51 } 52 53 class InstanceProvider: Provider { 54 private Object instance; 55 56 this(Object instance) { 57 this.instance = instance; 58 } 59 60 Object get() { 61 return this.instance; 62 } 63 } 64 65 private T create(T)(Container container) { 66 auto instance = cast(T) _d_newclass(T.classinfo); 67 mixin(generateCtor!T); 68 return instance; 69 } 70 71 unittest { 72 class Foo { } 73 class Bar { 74 this(Foo f) { } 75 } 76 class Fun { 77 this(Foo[] ff) { } 78 } 79 class A{ } 80 class B{ } 81 class Piss { 82 this(A a, B b) { } 83 } 84 85 import std.stdio; 86 import unit_threaded; 87 Bar b = new Bar(new Foo); 88 89 writeln("=== foo ==="); 90 string foo = generateCtor!Foo; 91 writeln(foo); 92 93 writeln("=== bar =="); 94 writeln(generateCtor!Bar); 95 96 //writeln("=== Foo[] =="); 97 //writeln(generateCtor!(Foo[])); 98 99 writeln("=== Fun =="); 100 writeln(generateCtor!(Fun)); 101 102 writeln("=== Piss =="); 103 writeln(generateCtor!(Piss)); 104 } 105 106 extern (C) Object _d_newclass(const TypeInfo_Class ci); 107 108 private string generateCtor(T)() { 109 enum ARGUMENT_SEPARATOR = ", "; 110 string code; 111 static if (hasMember!(T, "__ctor")) { 112 foreach (type; ParameterTypeTuple!(T.__ctor)) { 113 static if(is(type t == I[], I)) { 114 code ~= "import " ~ moduleName!I ~ ";"; 115 } else { 116 code ~= "import " ~ moduleName!type ~ ";"; 117 } 118 } 119 120 code ~= "instance.__ctor("; 121 foreach (type; ParameterTypeTuple!(T.__ctor)) { 122 code ~= "container.get!(" ~ fullyQualifiedName!type ~ ")" ~ 123 ARGUMENT_SEPARATOR; 124 } 125 code = chomp(code, ARGUMENT_SEPARATOR) ~ ");"; 126 } 127 return code; 128 }