Skip to content

Commit deae79f

Browse files
committed
add DI
1 parent 37c5b49 commit deae79f

File tree

7 files changed

+179
-6
lines changed

7 files changed

+179
-6
lines changed

Source/Library/CMakeLists.txt

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
1+
#file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
22

3-
add_library(SandboxLib ${SOURCES})
3+
add_library(SandboxLib
4+
LinkedList.cpp
5+
Map.cpp
6+
MemoryManager.cpp
7+
DependencyInjector.cpp
8+
)
49

510
target_include_directories(SandboxLib PUBLIC
611
h

Source/Library/Date.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <chrono>
21
#include "DetectOs.hpp"
2+
#include <chrono>
33

44
// skip for linux for now, c++20 must be fully implemented for clang - linux
55
#ifdef WINDOWS
@@ -219,6 +219,7 @@ namespace sd
219219
std::string Date::toString(const std::string &f) const { return std::format(f, ch::zt{timeZone(), timePoint()}); }
220220

221221
Date Date::toUtcTimeZone() const { return Date{*this}.changeTimeZoneToUtc(); }
222+
222223
Date Date::toLocalTimeZone() const { return Date{*this}.changeTimeZoneToLocal(); }
223224
Date Date::toDefaultTimeZone() const { return Date{*this}.changeTimeZoneToDefault(); }
224225
Date Date::toTimeZone(const std::string &tzName) const { return Date{*this}.changeTimeZone(tzName); }

Source/Library/DependencyInjector.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "DependencyInjector.hpp"
2+
3+
namespace sd
4+
{
5+
6+
}

Source/Library/Time.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <cmath>
55
#include <tuple>
66

7-
87
#ifdef WINDOWS
98
#include <format>
109

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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 *> &params) 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 *> &params) 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

Tests/CMakeLists.txt

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11

2-
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
2+
#file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp)
33

44
add_executable(Test
5-
${SOURCES}
5+
RunTests.cpp
6+
ListTest.cpp
7+
MapTest.cpp
8+
MemoryManagerTest.cpp
9+
DependencyInjectorTest.cpp
610
)
711

812
target_link_libraries(Test

Tests/DependencyInjectorTest.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <gtest/gtest.h>
2+
#include <iostream>
3+
#include <thread>
4+
5+
#include "DependencyInjector.hpp"
6+
7+
struct TestA
8+
{
9+
static TestA *constructor() { return new TestA(); };
10+
};
11+
12+
struct TestB
13+
{
14+
static TestB *constructor(TestA *a) { return new TestB(); };
15+
};
16+
17+
class DependencyInjector : public ::testing::Test
18+
{
19+
protected:
20+
sd::DependencyInjector di;
21+
22+
static void SetUpTestSuite() {}
23+
24+
DependencyInjector() {}
25+
26+
void SetUp() override {}
27+
28+
void TearDown() override {}
29+
30+
~DependencyInjector() {}
31+
32+
static void TearDownTestSuite() {}
33+
};
34+
35+
TEST_F(DependencyInjector, ExampleTest)
36+
{
37+
di.addSingeleton<TestA, TestA>();
38+
di.addSingeleton<TestB, TestB>();
39+
}

0 commit comments

Comments
 (0)