header_utils
Loading...
Searching...
No Matches
di.h
1
4
5#pragma once
6
7#if !defined(__cpp_concepts)
8#error "This library requires concepts"
9#endif
10
11#include <typeindex>
12#include <vector>
13#include <memory>
14#include <map>
15#include <functional>
16#include <string>
17#include <thread>
18#include "min-cpp-version/cpp20.h"
19
21{
34
44
45 struct DefaultImplementationStruct {};
46
48 constexpr inline DefaultImplementationStruct DefaultImplementation;
49
50 // TODO: Split into ContainerBuilder and Container (or [Dependency]Registry and [Dependency]Container)
51 // Oooh, idea: Container container = Container(Registry1(), Registry2(), ...);
52
54 struct Container
55 {
58
75 template <typename INTERFACE, typename IMPLEMENTATION, typename... PROPS>
76 void RegisterType(PROPS&&... properties);
77
79 template <typename INTERFACE>
80 bool HasAnyImplementationsOf() const;
81
84
88 template <typename INTERFACE>
89 std::shared_ptr<INTERFACE> Resolve();
90
93 template <typename INTERFACE>
94 std::shared_ptr<INTERFACE> ResolveByName(std::string_view name);
95
97 template <typename INTERFACE>
98 std::vector<std::shared_ptr<INTERFACE>> ResolveAll();
99
101
104
120 template <typename TYPE>
121 std::shared_ptr<TYPE> Create();
122
124 template <typename TYPE>
125 std::unique_ptr<TYPE> CreateRaw();
126
129 {
130 mDebugStore.clear();
131 mContainers.clear();
132 mParentContainer = nullptr;
133 }
134
136
138 auto const& Containers() const { return mContainers; }
139
141 auto const& DebugStore() const { return mDebugStore; }
142
143
144 private:
145
146 struct BaseInterfaceContainer
147 {
148 virtual ~BaseInterfaceContainer() noexcept = default;
149 explicit BaseInterfaceContainer(Lifetime default_lifetime) : DefaultLifetime(default_lifetime) {}
150 Lifetime DefaultLifetime = Lifetime::Default;
151 virtual bool HasAnyImplementations() const = 0;
152 };
153
154 template <typename INTERFACE>
155 struct InterfaceContainer;
156
157 template <typename INTERFACE>
158 struct ImplementationContainer;
159
160 template <typename INTERFACE>
161 InterfaceContainer<INTERFACE>& GetInterfaceContainer();
162
163 template <typename INTERFACE, typename IMPLEMENTATION>
164 ImplementationContainer<INTERFACE>* GetImplementationContainer();
165
166 std::map<std::type_index, std::unique_ptr<BaseInterfaceContainer>> mContainers;
167 std::vector<std::type_index> mResolutionStack;
168 std::vector<std::pair<std::shared_ptr<void>, std::function<void(Container&, std::shared_ptr<void>)>>> mCreationsToReport;
169 Container* mParentContainer = nullptr;
170
171 std::map<void const*, std::pair<std::type_index, std::weak_ptr<void>>> mDebugStore;
172
173 template <typename INSTANCE>
174 void ReportCreation(std::shared_ptr<INSTANCE> const& obj, std::function<void(Container&, std::shared_ptr<void>)> func);
175
176 void ReportAwaitingCreations()
177 {
178 auto creations = std::exchange(mCreationsToReport, {});
179 for (auto&& [ptr, callback] : creations)
180 callback(*this, std::move(ptr));
181 }
182
183 template <typename INTERFACE, typename T>
184 std::shared_ptr<INTERFACE> Instantiate(T& factory);
185 };
186
188 template <typename T>
189 concept has_default_lifetime = requires { { T::DefaultLifetime } -> std::convertible_to<Lifetime>; };
190
192}
193
194
195#include "di_impl.h"
If the interface or implementation has a DefaultLifetime static member field, that specified lifetime...
Definition di.h:189
constexpr DefaultImplementationStruct DefaultImplementation
Used to specify an implementation is the default one for the interface being registered.
Definition di.h:48
Lifetime
Specifies the lifetime of an implementation.
Definition di.h:37
@ WeakSingleton
Same as InstanceSingleton, but will not hold on to an instance, so when your last shared_ptr to it wi...
Definition di.h:41
@ InstanceSingleton
If a singleton instance of the implementation has not yet been created, it will be created and return...
Definition di.h:40
@ ThreadSingleton
Same as InstanceSingleton, but each thread gets its own instance.
Definition di.h:42
@ Default
Does not specify which lifetime of the implementation you want; you will be given one that's availabl...
Definition di.h:38
@ Transient
Will always give you a freshly instantiated implementation object when requesting the interface.
Definition di.h:39
The container for implementations; used to request interfaces.
Definition di.h:55
std::shared_ptr< TYPE > Create()
Creates a new (shared pointer to an) object of TYPE, resolving any interface pointer parameters its c...
Definition di_impl.h:414
std::shared_ptr< INTERFACE > Resolve()
Returns a pointer to an implementation of INTERFACE.
Definition di_impl.h:390
std::unique_ptr< TYPE > CreateRaw()
Same as Create, but returns a unique_ptr to the new object.
Definition di_impl.h:420
std::vector< std::shared_ptr< INTERFACE > > ResolveAll()
Will return a vector of all available implementations of INTERFACE; useful for interfaces like image_...
Definition di_impl.h:408
void DestroyAll()
Unregisters all the registered implementations and removes any pointers to their instances.
Definition di.h:128
std::shared_ptr< INTERFACE > ResolveByName(std::string_view name)
Returns a pointer to an implementation of INTERFACE with the name name If an implementation with that...
Definition di_impl.h:396
bool HasAnyImplementationsOf() const
Checks if there are any implementation registered for INTERFACE.
Definition di_impl.h:362
Lifetime DefaultLifetime
The default lifetime of implementations in this container, unless specified otherwise by the interfac...
Definition di.h:57
void RegisterType(PROPS &&... properties)
Registers the type IMPLEMENTATION as an implementation of INTERFACE.
Definition di_impl.h:370