plugify 1.2.8
Loading...
Searching...
No Matches
service_locator.hpp
1#pragma once
2
3#include <memory>
4#include <typeindex>
5#include <unordered_map>
6
7namespace plugify {
11 enum class ServiceLifetime {
12 Transient, // New instance each time
13 Scoped, // One instance per scope
14 Singleton // One instance globally
15 };
16
20 class PLUGIFY_API ServiceLocator {
21 public:
24
25 // Delete copy operations
26 ServiceLocator(const ServiceLocator&) = delete;
27 ServiceLocator& operator=(const ServiceLocator&) = delete;
28
29 // Move operations
31 ServiceLocator& operator=(ServiceLocator&&) noexcept;
32
33 // ============================================
34 // Registration Methods
35 // ============================================
36
40 template <typename Interface, typename Implementation = Interface>
41 void RegisterInstance(std::shared_ptr<Implementation> instance)
42 requires(std::is_base_of_v<Interface, Implementation>)
43 {
44 RegisterInstanceInternal(std::type_index(typeid(Interface)), instance);
45 }
46
50 template <typename Interface>
52 std::function<std::shared_ptr<Interface>()> factory,
53 ServiceLifetime lifetime = ServiceLifetime::Transient
54 ) {
55 RegisterFactoryInternal(
56 std::type_index(typeid(Interface)),
57 [factory]() -> std::shared_ptr<void> { return factory(); },
58 lifetime
59 );
60 }
61
65 template <typename Interface, typename Implementation = Interface>
66 void RegisterType(ServiceLifetime lifetime = ServiceLifetime::Transient)
67 requires(std::is_base_of_v<Interface, Implementation> && std::is_default_constructible_v<Implementation>)
68 {
69 RegisterFactory<Interface>([]() { return std::make_shared<Implementation>(); }, lifetime);
70 }
71
75 template <typename Interface, typename Implementation, typename... Dependencies>
77 std::function<std::shared_ptr<Implementation>(Dependencies...)> constructor,
78 ServiceLifetime lifetime = ServiceLifetime::Transient
79 )
80 requires(std::is_base_of_v<Interface, Implementation>)
81 {
82 RegisterFactory<Interface>(
83 [this, constructor]() -> std::shared_ptr<Interface> {
84 return constructor(Resolve<Dependencies>()...);
85 },
86 lifetime
87 );
88 }
89
93 template <typename Interface, typename Implementation = Interface>
94 void RegisterInstanceIfMissing(std::shared_ptr<Implementation> instance)
95 requires(std::is_base_of_v<Interface, Implementation>)
96 {
97 auto type = std::type_index(typeid(Interface));
98 if (!IsRegisteredInternal(type)) {
99 RegisterInstanceInternal(type, instance);
100 }
101 }
102
106 template <typename Interface>
108 std::function<std::shared_ptr<Interface>()> factory,
109 ServiceLifetime lifetime = ServiceLifetime::Transient
110 ) {
111 auto type = std::type_index(typeid(Interface));
112 if (!IsRegisteredInternal(type)) {
113 RegisterFactoryInternal(
114 type,
115 [factory]() -> std::shared_ptr<void> { return factory(); },
116 lifetime
117 );
118 }
119 }
120
124 template <typename Interface, typename Implementation = Interface>
125 void RegisterTypeIfMissing(ServiceLifetime lifetime = ServiceLifetime::Transient)
126 requires(std::is_base_of_v<Interface, Implementation> && std::is_default_constructible_v<Implementation>)
127 {
128 RegisterFactoryIfMissing<Interface>(
129 []() { return std::make_shared<Implementation>(); },
130 lifetime
131 );
132 }
133
137 template <typename Interface, typename Implementation, typename... Dependencies>
139 std::function<std::shared_ptr<Implementation>(Dependencies...)> constructor,
140 ServiceLifetime lifetime = ServiceLifetime::Transient
141 )
142 requires(std::is_base_of_v<Interface, Implementation>)
143 {
144 RegisterFactoryIfMissing<Interface>(
145 [this, constructor]() -> std::shared_ptr<Interface> {
146 return constructor(Resolve<Dependencies>()...);
147 },
148 lifetime
149 );
150 }
151
152 // ============================================
153 // Resolution Methods
154 // ============================================
155
159 template <typename Interface>
160 [[nodiscard]] std::shared_ptr<Interface> Resolve() const {
161 return std::static_pointer_cast<Interface>(
162 ResolveInternal(std::type_index(typeid(Interface)))
163 );
164 }
165
169 template <typename Interface>
170 [[nodiscard]] std::shared_ptr<Interface> TryResolve() const noexcept {
171 auto result = TryResolveInternal(std::type_index(typeid(Interface)));
172 return result ? std::static_pointer_cast<Interface>(result) : nullptr;
173 }
174
178 template <typename Interface>
179 [[nodiscard]] bool IsRegistered() const {
180 return IsRegisteredInternal(std::type_index(typeid(Interface)));
181 }
182
183 // ============================================
184 // Non-template public methods
185 // ============================================
186
191
195 void EndScope();
196
200 void Clear();
201
205 [[nodiscard]] size_t Count() const;
206
207 // ============================================
208 // Builder Pattern (Nested class for convenience)
209 // ============================================
210 class PLUGIFY_API ServiceBuilder {
211 public:
212 explicit ServiceBuilder(ServiceLocator& locator);
214
215 template <typename Interface, typename Implementation = Interface>
216 ServiceBuilder& AddSingleton() {
217 _locator.RegisterType<Interface, Implementation>(ServiceLifetime::Singleton);
218 return *this;
219 }
220
221 template <typename Interface>
222 ServiceBuilder& AddSingleton(std::shared_ptr<Interface> instance) {
223 _locator.RegisterInstance<Interface>(std::move(instance));
224 return *this;
225 }
226
227 template <typename Interface, typename Implementation = Interface>
228 ServiceBuilder& AddTransient() {
229 _locator.RegisterType<Interface, Implementation>(ServiceLifetime::Transient);
230 return *this;
231 }
232
233 template <typename Interface>
234 ServiceBuilder& AddFactory(std::function<std::shared_ptr<Interface>()> factory) {
235 _locator.RegisterFactory<Interface>(std::move(factory));
236 return *this;
237 }
238
239 private:
240 ServiceLocator& _locator;
241 };
242
243 ServiceBuilder Services();
244
245 private:
246 // Internal non-template methods (implemented in .cpp)
247 void RegisterInstanceInternal(std::type_index type, std::shared_ptr<void> instance);
248 void RegisterFactoryInternal(
249 std::type_index type,
250 std::function<std::shared_ptr<void>()> factory,
251 ServiceLifetime lifetime
252 );
253 [[nodiscard]] std::shared_ptr<void> ResolveInternal(std::type_index type) const;
254 [[nodiscard]] std::shared_ptr<void> TryResolveInternal(std::type_index type) const noexcept;
255 [[nodiscard]] bool IsRegisteredInternal(std::type_index type) const;
256
257 // PIMPL
258 PLUGIFY_ACCESS : struct Impl;
259 PLUGIFY_NO_DLL_EXPORT_WARNING(std::unique_ptr<Impl> _impl;)
260 };
261
262 // ============================================
263 // RAII Scope Guard
264 // ============================================
265 class PLUGIFY_API ScopedServiceLocator {
266 public:
267 explicit ScopedServiceLocator(ServiceLocator& locator);
269
270 // Delete copy/move
272 ScopedServiceLocator& operator=(const ScopedServiceLocator&) = delete;
274 ScopedServiceLocator& operator=(ScopedServiceLocator&&) = delete;
275
276 private:
277 ServiceLocator& _locator;
278 };
279}
DI Container / Service Locator with PIMPL.
void EndScope()
End current scope.
void RegisterFactory(std::function< std::shared_ptr< Interface >()> factory, ServiceLifetime lifetime=ServiceLifetime::Transient)
Register a factory function.
void RegisterWithDependencies(std::function< std::shared_ptr< Implementation >(Dependencies...)> constructor, ServiceLifetime lifetime=ServiceLifetime::Transient)
Register with dependency injection.
std::shared_ptr< Interface > TryResolve() const noexcept
Try to resolve a service (returns nullptr if not found)
std::shared_ptr< Interface > Resolve() const
Resolve a service.
void RegisterInstanceIfMissing(std::shared_ptr< Implementation > instance)
Register a concrete instance if missing (singleton)
void RegisterTypeIfMissing(ServiceLifetime lifetime=ServiceLifetime::Transient)
Register a type with automatic construction.
void RegisterWithDependenciesIfMissing(std::function< std::shared_ptr< Implementation >(Dependencies...)> constructor, ServiceLifetime lifetime=ServiceLifetime::Transient)
Register with dependency injection.
bool IsRegistered() const
Check if a service is registered.
void RegisterFactoryIfMissing(std::function< std::shared_ptr< Interface >()> factory, ServiceLifetime lifetime=ServiceLifetime::Transient)
Register a factory function.
void BeginScope()
Create a new scope (for scoped services)
size_t Count() const
Get the number of registered services.
void RegisterType(ServiceLifetime lifetime=ServiceLifetime::Transient)
Register a type with automatic construction.
void Clear()
Clear all registrations.
void RegisterInstance(std::shared_ptr< Implementation > instance)
Register a concrete instance (singleton)