1
+ #pragma once
2
+
3
+ #include < algorithm>
4
+ #include < functional>
5
+ #include < memory>
6
+ #include < typeindex>
7
+ #include < typeinfo>
8
+ #include < unordered_map>
9
+ #include < vector>
10
+
11
+ namespace sd
12
+ {
13
+
14
+ class DependencyInjector
15
+ {
16
+ private:
17
+ template <class T > struct Constructor
18
+ {
19
+ T ctor;
20
+ Constructor (T ctor) : ctor(ctor) {}
21
+ };
22
+
23
+ struct IConstructionInfo
24
+ {
25
+ virtual std::type_index getTypeIndex () const = 0;
26
+
27
+ virtual const std::vector<std::type_index> &getParamsTypeIndexes () const = 0;
28
+
29
+ virtual void *construct (const std::vector<void *> ¶ms) const = 0;
30
+
31
+ virtual ~IConstructionInfo () {}
32
+ };
33
+
34
+ template <class Type , class Param1 > class ConstructionInfo final : public IConstructionInfo
35
+ {
36
+ private:
37
+ std::type_index _typeIndex = typeid (Type);
38
+ std::vector<std::type_index> _params;
39
+ Type *(*_ctor)(Param1 *);
40
+
41
+ public:
42
+ ConstructionInfo (Constructor<Type *(*)(Param1 *)> constructor)
43
+ {
44
+ _ctor = constructor.ctor ;
45
+ _params = {typeid (Param1)};
46
+ }
47
+
48
+ std::type_index getTypeIndex () const { return _typeIndex; }
49
+
50
+ const std::vector<std::type_index> &getParamsTypeIndexes () const { return _params; };
51
+
52
+ void *construct (const std::vector<void *> ¶ms) const { return (*_ctor)((Param1 *)params[0 ]); };
53
+ };
54
+
55
+ private:
56
+ std::unordered_map<std::type_index, std::unique_ptr<IConstructionInfo>> _registered;
57
+ std::unordered_map<std::type_index, void *> _objectsMap;
58
+
59
+ public:
60
+ template <class I , class T > void addSingeleton ()
61
+ {
62
+ // todo check if T inherits from/implements I
63
+ auto cons = Constructor{T::constructor};
64
+ auto i = new ConstructionInfo (cons);
65
+ _registered.insert ({typeid (I), std::unique_ptr<IConstructionInfo>(i)});
66
+ }
67
+
68
+ template <class I > I *get () { return (I *)get (typeid (I)); }
69
+
70
+ void build ()
71
+ {
72
+ for (auto &objectToBuild : _registered)
73
+ {
74
+ auto &[index , constructionInfo] = objectToBuild;
75
+ if (!get (index ))
76
+ {
77
+ make (index , *constructionInfo);
78
+ }
79
+ }
80
+ }
81
+
82
+ private:
83
+ void *make (std::type_index typeIndex, IConstructionInfo &info)
84
+ {
85
+ std::vector<void *> params;
86
+ auto &indexes = info.getParamsTypeIndexes ();
87
+ for (auto index : indexes)
88
+ {
89
+ if (auto object = get (index ))
90
+ {
91
+ params.push_back (object);
92
+ }
93
+ else if (auto constructionInfo = getRegistered (index ))
94
+ {
95
+ params.push_back (make (index , *constructionInfo));
96
+ }
97
+ else
98
+ {
99
+ // todo
100
+ }
101
+ }
102
+ auto object = info.construct (params);
103
+ _objectsMap.insert ({typeIndex, object});
104
+ return object;
105
+ }
106
+
107
+ void *get (std::type_index index)
108
+ {
109
+ auto pair = _objectsMap.find (index );
110
+ return pair != _objectsMap.end () ? pair->second : nullptr ;
111
+ }
112
+
113
+ IConstructionInfo *getRegistered (std::type_index index)
114
+ {
115
+ auto pair = _registered.find (index );
116
+ return pair != _registered.end () ? pair->second .get () : nullptr ;
117
+ }
118
+ };
119
+ } // namespace sd
0 commit comments