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 }