1
1
#pragma once
2
2
3
3
#include < algorithm>
4
+ #include < exception>
4
5
#include < functional>
5
6
#include < memory>
7
+ #include < stdexcept>
8
+ #include < tuple>
9
+ #include < type_traits>
6
10
#include < typeindex>
7
11
#include < typeinfo>
8
12
#include < unordered_map>
9
- #include < vector>
13
+
14
+ #include " Reflection.hpp"
10
15
11
16
namespace sd
12
17
{
13
18
14
19
class DependencyInjector
15
20
{
16
21
private:
17
- template <typename T> struct FunctionTraits ;
22
+ struct IObjectHolder
23
+ {
24
+ virtual void *getObjectPtr () const = 0;
25
+
26
+ virtual void destroyObject () = 0;
27
+ virtual bool isValid () const = 0;
28
+
29
+ virtual ~IObjectHolder () {}
30
+ };
31
+
32
+ template <class T > class ObjectHolder final : public IObjectHolder
33
+ {
34
+ private:
35
+ std::unique_ptr<T> _objectPtr;
36
+
37
+ ObjectHolder (T *objectPtr) : _objectPtr(objectPtr) {}
38
+
39
+ public:
40
+ ObjectHolder (const ObjectHolder &) = delete ;
41
+ ObjectHolder &operator =(const ObjectHolder &) = delete ;
18
42
19
- template <typename R, typename ... Args> struct FunctionTraits <std::function<R(Args...)>>
43
+ template <class ... Args> static std::unique_ptr<ObjectHolder<T>> create (Args &&...params)
44
+ {
45
+ auto objectPtr = new T{std::forward<Args>(params)...};
46
+ return std::unique_ptr<ObjectHolder<T>>(new ObjectHolder{objectPtr});
47
+ };
48
+
49
+ T *getTypedObjectPtr () const { return _objectPtr.get (); }
50
+ void *getObjectPtr () const final { return _objectPtr.get (); }
51
+
52
+ void destroyObject () { _objectPtr.reset (); }
53
+ bool isValid () const final { return !!getObjectPtr (); }
54
+ operator bool () const { return isValid (); }
55
+ };
56
+
57
+ template <class T > struct ConstrutorTraits
20
58
{
21
- static const size_t nargs = sizeof ...(Args);
59
+ using Type = T;
60
+ using TupleArgs = AsTuple<Type>;
22
61
23
- typedef R result_type ;
62
+ static constexpr size_t ArgsSize = std::tuple_size_v<TupleArgs> ;
24
63
25
- template <size_t i > struct arg
64
+ template <size_t I > struct Arg
26
65
{
27
- typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
66
+ using Type = typename std::tuple_element<I, TupleArgs>::type;
67
+ using RawType = typename std::remove_cvref_t <std::remove_pointer_t <Type>>;
68
+ using RawTypePtr = typename std::add_pointer_t <RawType>;
28
69
};
29
70
};
30
71
@@ -34,69 +75,85 @@ namespace sd
34
75
35
76
virtual const std::vector<std::type_index> getParamsTypeIndexes () const = 0;
36
77
37
- virtual void * construct (const std::vector<void *> ¶ms) const = 0;
78
+ virtual std::unique_ptr<IObjectHolder> construct (const std::vector<void *> ¶ms) const = 0;
38
79
39
80
virtual ~IConstructionInfo () {}
40
81
};
41
82
42
- template <typename R, typename ... Args > class ConstructionInfo final : public IConstructionInfo
83
+ template <typename T > class ConstructionInfo final : public IConstructionInfo
43
84
{
44
85
private:
45
- using ConstructorTraits = FunctionTraits<std::function<R(Args...)> >;
46
- std::function<R(Args...)> _constructor ;
86
+ using ConstructorTraits = ConstrutorTraits<T >;
87
+ using Indices = std::make_index_sequence<ConstructorTraits::ArgsSize> ;
47
88
48
89
public:
49
- ConstructionInfo (const std::function<R(Args...)> &constructor) { _constructor = constructor; }
50
-
51
- std::type_index getTypeIndex () const { return typeid (typename ConstructorTraits::result_type); }
90
+ std::type_index getTypeIndex () const { return typeid (typename ConstructorTraits::Type); }
52
91
53
92
const std::vector<std::type_index> getParamsTypeIndexes () const
54
93
{
55
- if constexpr (ConstructorTraits::nargs == 0 )
56
- {
57
- return {};
58
- }
59
- else if constexpr (ConstructorTraits::nargs == 1 )
60
- {
61
- return {typeid (typename ConstructorTraits::template arg<0 >::type)};
62
- }
63
- else if constexpr (ConstructorTraits::nargs == 2 )
94
+ return getParamsTypeIndexesInt (Indices{});
95
+ };
96
+
97
+ std::unique_ptr<IObjectHolder> construct (const std::vector<void *> ¶ms) const
98
+ {
99
+ if (params.size () != ConstructorTraits::ArgsSize)
64
100
{
65
- return {typeid (typename ConstructorTraits::template arg<0 >::type),
66
- typeid (typename ConstructorTraits::template arg<1 >::type)};
101
+ throw std::runtime_error (" Wrong Argument vector size" );
67
102
}
103
+ return constructInt (Indices{}, params);
68
104
};
69
105
70
- void *construct (const std::vector<void *> ¶ms) const
106
+ private:
107
+ template <size_t ... I>
108
+ const std::vector<std::type_index> getParamsTypeIndexesInt (std::index_sequence<I...> seq) const
71
109
{
72
- if constexpr (ConstructorTraits::nargs == 0 )
110
+ return std::vector<std::type_index>{(typeid (typename ConstructorTraits::template Arg<I>::RawType))...};
111
+ };
112
+
113
+ template <size_t ... I>
114
+ std::unique_ptr<ObjectHolder<T>> constructInt (std::index_sequence<I...> seq,
115
+ const std::vector<void *> ¶ms) const
116
+ {
117
+ return ObjectHolder<T>::create (getParameter<I>(params)...);
118
+ };
119
+
120
+ template <size_t I> constexpr auto getParameter (const std::vector<void *> ¶ms) const
121
+ {
122
+ if constexpr (std::is_pointer_v<typename ConstructorTraits::template Arg<I>::Type>)
73
123
{
74
- return _constructor () ;
124
+ return ( typename ConstructorTraits:: template Arg<I>::RawTypePtr)params[I] ;
75
125
}
76
- else if constexpr (ConstructorTraits::nargs == 1 )
126
+ else if constexpr (std::is_reference_v< typename ConstructorTraits::template Arg<I>::Type> )
77
127
{
78
- return _constructor (( typename ConstructorTraits::template arg< 0 >::type)( params[0 ])) ;
128
+ return *( typename ConstructorTraits::template Arg<I >::RawTypePtr) params[I] ;
79
129
}
80
- else if constexpr (ConstructorTraits::nargs == 2 )
130
+ else
81
131
{
132
+ static_assert (true , " Could not fetch parameters" );
82
133
}
83
- };
134
+ }
84
135
};
85
136
86
137
private:
87
138
std::unordered_map<std::type_index, std::unique_ptr<IConstructionInfo>> _registered;
88
- std::unordered_map<std::type_index, void * > _objectsMap;
139
+ std::unordered_map<std::type_index, std::unique_ptr<IObjectHolder> > _objectsMap;
89
140
90
141
public:
91
142
template <class I , class T > void addSingeleton ()
92
143
{
93
- // todo check if T inherits from/implements I
94
- std::function<decltype (T::constructor)> ff{&T::constructor};
95
- auto i = new ConstructionInfo (ff);
96
- _registered.insert ({typeid (I *), std::unique_ptr<IConstructionInfo>(i)});
144
+ 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>>()});
97
146
}
98
147
99
- template <class I > I *get () { return (I *)get (typeid (I *)); }
148
+ template <class I > I *getPtr () { return (I *)get (typeid (I)); }
149
+ template <class I > I &getRef ()
150
+ {
151
+ if (auto ptr = getPtr<I>())
152
+ {
153
+ return *ptr;
154
+ }
155
+ throw std::exception_ptr ();
156
+ }
100
157
101
158
void build ()
102
159
{
@@ -127,32 +184,25 @@ namespace sd
127
184
}
128
185
else
129
186
{
130
- // todo
187
+ throw std::runtime_error ( " Services build failed " );
131
188
}
132
189
}
133
- auto object = info.construct (params);
134
- _objectsMap.insert ({typeIndex, object});
135
- return object;
190
+ auto objectHolder = info.construct (params);
191
+ auto rawPtr = objectHolder->getObjectPtr ();
192
+ _objectsMap.insert ({typeIndex, std::move (objectHolder)});
193
+ return rawPtr;
136
194
}
137
195
138
196
void *get (std::type_index index)
139
197
{
140
198
auto pair = _objectsMap.find (index );
141
- return pair != _objectsMap.end () ? pair->second : nullptr ;
199
+ return pair != _objectsMap.end () ? pair->second -> getObjectPtr () : nullptr ;
142
200
}
143
201
144
202
IConstructionInfo *getRegistered (std::type_index index)
145
203
{
146
204
auto pair = _registered.find (index );
147
- if (pair != _registered.end ())
148
- {
149
- auto &ob = pair->second ;
150
- return ob.get ();
151
- }
152
- else
153
- {
154
- return nullptr ;
155
- }
205
+ return pair != _registered.end () ? pair->second .get () : nullptr ;
156
206
}
157
207
};
158
208
} // namespace sd
0 commit comments