Skip to content

Commit 8ec26fc

Browse files
committed
add functionalities
1 parent 9373003 commit 8ec26fc

File tree

1 file changed

+110
-28
lines changed

1 file changed

+110
-28
lines changed

Source/Library/h/DependencyInjector.hpp

Lines changed: 110 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,56 @@
55
#include <functional>
66
#include <memory>
77
#include <stdexcept>
8+
#include <string>
89
#include <tuple>
910
#include <type_traits>
1011
#include <typeindex>
1112
#include <typeinfo>
1213
#include <unordered_map>
14+
#include <utility>
1315

1416
#include "Reflection.hpp"
1517

1618
namespace sd
1719
{
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+
};
1858

1959
class DependencyInjector
2060
{
@@ -26,15 +66,18 @@ namespace sd
2666
virtual void destroyObject() = 0;
2767
virtual bool isValid() const = 0;
2868

69+
virtual const char *getToken() const = 0;
70+
2971
virtual ~IObjectHolder() {}
3072
};
3173

3274
template <class T> class ObjectHolder final : public IObjectHolder
3375
{
3476
private:
3577
std::unique_ptr<T> _objectPtr;
78+
const char *_token = nullptr;
3679

37-
ObjectHolder(T *objectPtr) : _objectPtr(objectPtr) {}
80+
ObjectHolder(T *objectPtr, const char *token = nullptr) : _objectPtr(objectPtr), _token(token) {}
3881

3982
public:
4083
ObjectHolder(const ObjectHolder &) = delete;
@@ -71,6 +114,8 @@ namespace sd
71114

72115
struct IConstructionInfo
73116
{
117+
virtual const Scope &getScope() const = 0;
118+
74119
virtual std::type_index getTypeIndex() const = 0;
75120

76121
virtual const std::vector<std::type_index> getParamsTypeIndexes() const = 0;
@@ -85,8 +130,13 @@ namespace sd
85130
private:
86131
using ConstructorTraits = ConstrutorTraits<T>;
87132
using Indices = std::make_index_sequence<ConstructorTraits::ArgsSize>;
133+
Scope _scope;
88134

89135
public:
136+
ConstructionInfo(const Scope &scope) : _scope(scope) {}
137+
138+
const Scope &getScope() const { return _scope; };
139+
90140
std::type_index getTypeIndex() const { return typeid(typename ConstructorTraits::Type); }
91141

92142
const std::vector<std::type_index> getParamsTypeIndexes() const
@@ -135,20 +185,31 @@ namespace sd
135185
};
136186

137187
private:
188+
using ObjKey = std::pair<std::type_index, const char *>;
138189
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;
140191

141192
public:
142193
template <class I, class T> void addSingeleton()
143194
{
144195
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))});
146207
}
147208

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)
150211
{
151-
if (auto ptr = getPtr<I>())
212+
if (auto ptr = getPtr<I>(token))
152213
{
153214
return *ptr;
154215
}
@@ -160,42 +221,63 @@ namespace sd
160221
for (auto &objectToBuild : _registered)
161222
{
162223
auto &[index, constructionInfo] = objectToBuild;
163-
if (!get(index))
224+
if (constructionInfo->getScope().isSingeleton() && !getFromObjectsMap(index))
164225
{
165-
make(index, *constructionInfo);
226+
createAndRegister(index, constructionInfo->getScope());
166227
}
167228
}
168229
}
169230

170231
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)
172242
{
173243
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();
175250
for (auto index : indexes)
176251
{
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");
189275
}
190-
auto objectHolder = info.construct(params);
191-
auto rawPtr = objectHolder->getObjectPtr();
192-
_objectsMap.insert({typeIndex, std::move(objectHolder)});
193-
return rawPtr;
194276
}
195277

196-
void *get(std::type_index index)
278+
void *getFromObjectsMap(std::type_index index, const char *token = nullptr)
197279
{
198-
auto pair = _objectsMap.find(index);
280+
auto pair = _objectsMap.find({index, token});
199281
return pair != _objectsMap.end() ? pair->second->getObjectPtr() : nullptr;
200282
}
201283

0 commit comments

Comments
 (0)