5
5
#include < functional>
6
6
#include < memory>
7
7
#include < stdexcept>
8
+ #include < string>
8
9
#include < tuple>
9
10
#include < type_traits>
10
11
#include < typeindex>
11
12
#include < typeinfo>
12
13
#include < unordered_map>
14
+ #include < utility>
13
15
14
16
#include " Reflection.hpp"
15
17
16
18
namespace sd
17
19
{
20
+ template <const char *T, class S > class Token
21
+ {
22
+ private:
23
+ static constexpr const char *Value = T;
24
+ S *_object;
25
+
26
+ public:
27
+ static std::string getToken () { return Value; }
28
+
29
+ Token (S *object) : _object(object) {}
30
+
31
+ S *get () const { return _object; }
32
+ };
33
+
34
+ enum ScopeType
35
+ {
36
+ Singeleton,
37
+ Tokenized,
38
+ Scoped,
39
+ };
40
+
41
+ struct Scope
42
+ {
43
+ public:
44
+ static Scope singeleton () { return {ScopeType::Singeleton}; }
45
+ static Scope scoped () { return {ScopeType::Scoped}; }
46
+ static Scope tokenized (const char *token) { return {token}; }
47
+
48
+ const ScopeType type;
49
+ const char *token = nullptr ;
50
+
51
+ Scope (ScopeType type) : type(type) {}
52
+ Scope (const char *token) : type(ScopeType::Tokenized), token(token) {}
53
+
54
+ bool isSingeleton () const { return type == ScopeType::Singeleton; }
55
+ bool isScoped () const { return type == ScopeType::Scoped; }
56
+ bool isTokenized () const { return type == ScopeType::Tokenized; }
57
+ };
18
58
19
59
class DependencyInjector
20
60
{
@@ -26,15 +66,18 @@ namespace sd
26
66
virtual void destroyObject () = 0;
27
67
virtual bool isValid () const = 0;
28
68
69
+ virtual const char *getToken () const = 0;
70
+
29
71
virtual ~IObjectHolder () {}
30
72
};
31
73
32
74
template <class T > class ObjectHolder final : public IObjectHolder
33
75
{
34
76
private:
35
77
std::unique_ptr<T> _objectPtr;
78
+ const char *_token = nullptr ;
36
79
37
- ObjectHolder (T *objectPtr) : _objectPtr(objectPtr) {}
80
+ ObjectHolder (T *objectPtr, const char *token = nullptr ) : _objectPtr(objectPtr), _token(token ) {}
38
81
39
82
public:
40
83
ObjectHolder (const ObjectHolder &) = delete ;
@@ -71,6 +114,8 @@ namespace sd
71
114
72
115
struct IConstructionInfo
73
116
{
117
+ virtual const Scope &getScope () const = 0;
118
+
74
119
virtual std::type_index getTypeIndex () const = 0;
75
120
76
121
virtual const std::vector<std::type_index> getParamsTypeIndexes () const = 0;
@@ -85,8 +130,13 @@ namespace sd
85
130
private:
86
131
using ConstructorTraits = ConstrutorTraits<T>;
87
132
using Indices = std::make_index_sequence<ConstructorTraits::ArgsSize>;
133
+ Scope _scope;
88
134
89
135
public:
136
+ ConstructionInfo (const Scope &scope) : _scope(scope) {}
137
+
138
+ const Scope &getScope () const { return _scope; };
139
+
90
140
std::type_index getTypeIndex () const { return typeid (typename ConstructorTraits::Type); }
91
141
92
142
const std::vector<std::type_index> getParamsTypeIndexes () const
@@ -135,20 +185,31 @@ namespace sd
135
185
};
136
186
137
187
private:
188
+ using ObjKey = std::pair<std::type_index, const char *>;
138
189
std::unordered_map<std::type_index, std::unique_ptr<IConstructionInfo>> _registered;
139
- std::unordered_map<std::type_index , std::unique_ptr<IObjectHolder>> _objectsMap;
190
+ std::unordered_map<ObjKey , std::unique_ptr<IObjectHolder>> _objectsMap;
140
191
141
192
public:
142
193
template <class I , class T > void addSingeleton ()
143
194
{
144
195
static_assert (std::is_base_of_v<I, T>, " Type T must inherit from I" );
145
- _registered.insert ({typeid (I), std::make_unique<ConstructionInfo<T>>()});
196
+ _registered.insert ({typeid (I), std::make_unique<ConstructionInfo<T>>(Scope::singeleton ())});
197
+ }
198
+ template <class I , class T > void addScoped ()
199
+ {
200
+ static_assert (std::is_base_of_v<I, T>, " Type T must inherit from I" );
201
+ _registered.insert ({typeid (I), std::make_unique<ConstructionInfo<T>>(Scope::scoped ())});
202
+ }
203
+ template <class I , class T > void addTokenized (const char *token)
204
+ {
205
+ static_assert (std::is_base_of_v<I, T>, " Type T must inherit from I" );
206
+ _registered.insert ({typeid (I), std::make_unique<ConstructionInfo<T>>(Scope::tokenized (token))});
146
207
}
147
208
148
- template <class I > I *getPtr () { return (I *)get (typeid (I)); }
149
- template <class I > I &getRef ()
209
+ template <class I > I *getPtr (const char *token = nullptr ) { return (I *)getFromObjectsMap (typeid (I), token ); }
210
+ template <class I > I &getRef (const char *token = nullptr )
150
211
{
151
- if (auto ptr = getPtr<I>())
212
+ if (auto ptr = getPtr<I>(token ))
152
213
{
153
214
return *ptr;
154
215
}
@@ -160,42 +221,63 @@ namespace sd
160
221
for (auto &objectToBuild : _registered)
161
222
{
162
223
auto &[index , constructionInfo] = objectToBuild;
163
- if (! get (index ))
224
+ if (constructionInfo-> getScope (). isSingeleton () && ! getFromObjectsMap (index ))
164
225
{
165
- make (index , * constructionInfo);
226
+ createAndRegister (index , constructionInfo-> getScope () );
166
227
}
167
228
}
168
229
}
169
230
170
231
private:
171
- void *make (std::type_index typeIndex, IConstructionInfo &info)
232
+ void *createAndRegister (std::type_index typeIndex, const Scope &scope)
233
+ {
234
+ auto objectHolder = create (typeIndex);
235
+ auto rawPtr = objectHolder->getObjectPtr ();
236
+ ObjKey key{typeIndex, scope.isTokenized () ? scope.token : nullptr };
237
+ _objectsMap.insert ({key, std::move (objectHolder)});
238
+ return rawPtr;
239
+ }
240
+
241
+ std::unique_ptr<IObjectHolder> create (std::type_index typeIndex)
172
242
{
173
243
std::vector<void *> params;
174
- auto &indexes = info.getParamsTypeIndexes ();
244
+ auto info = getRegistered (typeIndex);
245
+ if (!info)
246
+ {
247
+ // todo
248
+ }
249
+ auto &indexes = info->getParamsTypeIndexes ();
175
250
for (auto index : indexes)
176
251
{
177
- if (auto object = get (index ))
178
- {
179
- params.push_back (object);
180
- }
181
- else if (auto constructionInfo = getRegistered (index ))
182
- {
183
- params.push_back (make (index , *constructionInfo));
184
- }
185
- else
186
- {
187
- throw std::runtime_error (" Services build failed" );
188
- }
252
+ params.push_back (get (index ));
253
+ }
254
+ return info->construct (params);
255
+ }
256
+
257
+ void *get (std::type_index index, const Scope &scope = Scope::singeleton())
258
+ {
259
+ if (scope.isScoped ())
260
+ {
261
+ return create (index );
262
+ }
263
+ const char *token = scope.isTokenized () ? scope.token : nullptr ;
264
+ if (auto object = getFromObjectsMap (index , token))
265
+ {
266
+ return object;
267
+ }
268
+ else if (auto constructionInfo = getRegistered (index ))
269
+ {
270
+ params.push_back (make (index , *constructionInfo));
271
+ }
272
+ else
273
+ {
274
+ throw std::runtime_error (" Services build failed" );
189
275
}
190
- auto objectHolder = info.construct (params);
191
- auto rawPtr = objectHolder->getObjectPtr ();
192
- _objectsMap.insert ({typeIndex, std::move (objectHolder)});
193
- return rawPtr;
194
276
}
195
277
196
- void *get (std::type_index index)
278
+ void *getFromObjectsMap (std::type_index index, const char *token = nullptr )
197
279
{
198
- auto pair = _objectsMap.find (index );
280
+ auto pair = _objectsMap.find ({ index , token} );
199
281
return pair != _objectsMap.end () ? pair->second ->getObjectPtr () : nullptr ;
200
282
}
201
283
0 commit comments