Skip to content

Commit 9373003

Browse files
committed
first working implementation DI
1 parent 6fde20a commit 9373003

File tree

4 files changed

+234
-65
lines changed

4 files changed

+234
-65
lines changed
+102-52
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,71 @@
11
#pragma once
22

33
#include <algorithm>
4+
#include <exception>
45
#include <functional>
56
#include <memory>
7+
#include <stdexcept>
8+
#include <tuple>
9+
#include <type_traits>
610
#include <typeindex>
711
#include <typeinfo>
812
#include <unordered_map>
9-
#include <vector>
13+
14+
#include "Reflection.hpp"
1015

1116
namespace sd
1217
{
1318

1419
class DependencyInjector
1520
{
1621
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;
1842

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
2058
{
21-
static const size_t nargs = sizeof...(Args);
59+
using Type = T;
60+
using TupleArgs = AsTuple<Type>;
2261

23-
typedef R result_type;
62+
static constexpr size_t ArgsSize = std::tuple_size_v<TupleArgs>;
2463

25-
template <size_t i> struct arg
64+
template <size_t I> struct Arg
2665
{
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>;
2869
};
2970
};
3071

@@ -34,69 +75,85 @@ namespace sd
3475

3576
virtual const std::vector<std::type_index> getParamsTypeIndexes() const = 0;
3677

37-
virtual void *construct(const std::vector<void *> &params) const = 0;
78+
virtual std::unique_ptr<IObjectHolder> construct(const std::vector<void *> &params) const = 0;
3879

3980
virtual ~IConstructionInfo() {}
4081
};
4182

42-
template <typename R, typename... Args> class ConstructionInfo final : public IConstructionInfo
83+
template <typename T> class ConstructionInfo final : public IConstructionInfo
4384
{
4485
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>;
4788

4889
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); }
5291

5392
const std::vector<std::type_index> getParamsTypeIndexes() const
5493
{
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 *> &params) const
98+
{
99+
if (params.size() != ConstructorTraits::ArgsSize)
64100
{
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");
67102
}
103+
return constructInt(Indices{}, params);
68104
};
69105

70-
void *construct(const std::vector<void *> &params) const
106+
private:
107+
template <size_t... I>
108+
const std::vector<std::type_index> getParamsTypeIndexesInt(std::index_sequence<I...> seq) const
71109
{
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 *> &params) const
116+
{
117+
return ObjectHolder<T>::create(getParameter<I>(params)...);
118+
};
119+
120+
template <size_t I> constexpr auto getParameter(const std::vector<void *> &params) const
121+
{
122+
if constexpr (std::is_pointer_v<typename ConstructorTraits::template Arg<I>::Type>)
73123
{
74-
return _constructor();
124+
return (typename ConstructorTraits::template Arg<I>::RawTypePtr)params[I];
75125
}
76-
else if constexpr (ConstructorTraits::nargs == 1)
126+
else if constexpr (std::is_reference_v<typename ConstructorTraits::template Arg<I>::Type>)
77127
{
78-
return _constructor((typename ConstructorTraits::template arg<0>::type)(params[0]));
128+
return *(typename ConstructorTraits::template Arg<I>::RawTypePtr)params[I];
79129
}
80-
else if constexpr (ConstructorTraits::nargs == 2)
130+
else
81131
{
132+
static_assert(true, "Could not fetch parameters");
82133
}
83-
};
134+
}
84135
};
85136

86137
private:
87138
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;
89140

90141
public:
91142
template <class I, class T> void addSingeleton()
92143
{
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>>()});
97146
}
98147

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+
}
100157

101158
void build()
102159
{
@@ -127,32 +184,25 @@ namespace sd
127184
}
128185
else
129186
{
130-
// todo
187+
throw std::runtime_error("Services build failed");
131188
}
132189
}
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;
136194
}
137195

138196
void *get(std::type_index index)
139197
{
140198
auto pair = _objectsMap.find(index);
141-
return pair != _objectsMap.end() ? pair->second : nullptr;
199+
return pair != _objectsMap.end() ? pair->second->getObjectPtr() : nullptr;
142200
}
143201

144202
IConstructionInfo *getRegistered(std::type_index index)
145203
{
146204
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;
156206
}
157207
};
158208
} // namespace sd

Source/Library/h/Reflection.hpp

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
#include <utility>
3+
#include <vector>
4+
5+
namespace sd
6+
{
7+
template <typename T, int N> struct Tag
8+
{
9+
friend auto loophole(Tag<T, N>);
10+
constexpr friend int cloophole(Tag<T, N>);
11+
};
12+
13+
template <typename T, typename U, int N, bool B,
14+
typename = typename std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
15+
std::remove_cv_t<std::remove_reference_t<U>>>>>
16+
struct FnDef
17+
{
18+
friend auto loophole(Tag<T, N>) { return U{}; }
19+
constexpr friend int cloophole(Tag<T, N>) { return 0; }
20+
};
21+
22+
template <typename T, typename U, int N> struct FnDef<T, U, N, true>
23+
{
24+
};
25+
26+
template <typename T, int N> struct Cop
27+
{
28+
template <typename U, int M> static auto ins(...) -> int;
29+
template <typename U, int M, int = cloophole(Tag<T, M>{})> static auto ins(int) -> char;
30+
31+
template <typename U, int = sizeof(FnDef<T, U, N, sizeof(ins<U, N>(0)) == sizeof(char)>)> operator U();
32+
};
33+
34+
template <typename T, int... Ns> constexpr int fieldsNumber(...) { return sizeof...(Ns) - 1; }
35+
36+
template <typename T, int... Ns> constexpr auto fieldsNumber(int) -> decltype(T{Cop<T, Ns>{}...}, 0)
37+
{
38+
return fieldsNumber<T, Ns..., sizeof...(Ns)>(0);
39+
}
40+
41+
template <typename T, int... Ns> constexpr auto fieldsNumberCtor(int) -> decltype(T(Cop<T, Ns>{}...), 0)
42+
{
43+
return sizeof...(Ns);
44+
}
45+
46+
template <typename T, int... Ns> constexpr int fieldsNumberCtor(...)
47+
{
48+
return fieldsNumberCtor<T, Ns..., sizeof...(Ns)>(0);
49+
}
50+
51+
template <typename T, typename U> struct loopholeTuple;
52+
53+
template <typename T, int... Ns> struct loopholeTuple<T, std::integer_sequence<int, Ns...>>
54+
{
55+
using Type = std::tuple<decltype(loophole(Tag<T, Ns>{}))...>;
56+
};
57+
58+
template <typename T>
59+
using AsTuple = typename loopholeTuple<T, std::make_integer_sequence<int, fieldsNumberCtor<T>(0)>>::Type;
60+
} // namespace sd

0 commit comments

Comments
 (0)