solinject  1.0.0
C++17 Dependency Injection header-only library
RegisteredServices.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-or-later
2 
3 /*
4  * solinject - C++ Dependency Injection header-only library
5  * Copyright (C) 2022 SemperSolus0x3d
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
22 
23 #pragma once
24 
25 #include <map>
26 #include <vector>
27 #include <algorithm>
28 #include <memory>
29 #include <typeinfo>
30 #include <typeindex>
31 
32 #include "solinject/Defines.hpp"
33 #include "IService.hpp"
34 #include "IServiceTyped.hpp"
35 #include "SingletonService.hpp"
36 #include "TransientService.hpp"
37 #include "SharedService.hpp"
38 #include "ScopedService.hpp"
40 #include "solinject/Utils.hpp"
41 
42 namespace sol::di::impl
43 {
46  {
47  public:
52  template <class T>
54 
59  template <class T>
61 
64 
67 
70 
76  m_RegisteredServices(std::move(services))
77  {
78  }
79 
82  m_RegisteredServices(other.m_RegisteredServices)
83  {
84  }
85 
88  {
89  swap(*this, other);
90  }
91 
94  {
95  swap(*this, other);
96  return *this;
97  }
98 
101  {
102  swap(*this, other);
103  return *this;
104  }
105 
108  {
109  using std::swap;
110 
111  swap(a.m_RegisteredServices, b.m_RegisteredServices);
112  }
113 
120  {
121  for (auto& pair : other.m_RegisteredServices)
122  {
123  auto& source = pair.second;
124  auto& destination = m_RegisteredServices[pair.first];
125 
126  impl::ConcatenateVectors(destination, std::move(source));
127  }
128  }
129 
135  template<class T>
137  {
138  RegisterServiceInternal<T, SingletonService<T>>(factory);
139  }
140 
146  template<class T>
148  {
149  RegisterServiceInternal<T, SingletonService<T>>(instance);
150  }
151 
157  template<class T>
159  {
160  RegisterServiceInternal<T, TransientService<T>>(factory);
161  }
162 
168  template<class T>
170  {
171  RegisterServiceInternal<T, SharedService<T>>(factory);
172  }
173 
182  {
183  RegisterServiceInternal(type, diService);
184  }
185 
193  template<class T>
195  {
196  return GetServiceInternal<T, false>(container);
197  }
198 
206  template <class T>
207  ServicePtr<T> GetService(const Container& container) const
208  {
209  return GetServiceInternal<T, true>(container);
210  }
211 
219  template <class T>
221  {
222  using namespace std::string_literals;
223 
224  auto serviceIt = m_RegisteredServices.find(std::type_index(typeid(T)));
225 
226  if (serviceIt == m_RegisteredServices.end())
227  return std::vector<ServicePtr<T>>();
228 
229  auto& services = serviceIt->second;
230 
232  result.reserve(services.size());
233 
235  services.begin(),
236  services.end(),
237  std::back_inserter(result),
238  [this, &container](auto& diService)
239  {
240  return GetServiceInstance<T>(diService, container);
241  }
242  );
243 
244  return result;
245  }
246  private:
248  RegisteredServicesMap m_RegisteredServices;
249 
255  void RegisterServiceInternal(std::type_index type, DIServicePtr diService)
256  {
257  m_RegisteredServices[type].push_back(diService);
258  }
259 
266  template <class TService, class TDIService>
267  void RegisterServiceInternal(Factory<TService> factory)
268  {
269  RegisterServiceInternal(
270  std::type_index(typeid(TService)),
271  std::make_shared<TDIService>(factory)
272  );
273  }
274 
281  template <class TService, class TDIService>
282  void RegisterServiceInternal(ServicePtr<TService> instance)
283  {
284  solinject_req_assert(instance != nullptr);
285 
286  m_RegisteredServices[std::type_index(typeid(TService))].push_back(std::make_shared<TDIService>(instance));
287  }
288 
296  template <class T>
297  ServicePtr<T> GetServiceInstance(const DIServicePtr& diServicePtr, const Container& container) const
298  {
299  solinject_req_assert(diServicePtr != nullptr);
300 
301  auto castedDiServicePtr = std::dynamic_pointer_cast<IServiceTyped<T>>(diServicePtr);
302 
303  solinject_req_assert(castedDiServicePtr != nullptr && "The service is resolvable as T");
304 
305  return castedDiServicePtr->GetService(container);
306  }
307 
316  template <class T, bool nothrow>
317  ServicePtr<T> GetServiceInternal(const Container& container) const
318  {
319  using namespace std::string_literals;
320 
321  auto serviceIt = m_RegisteredServices.find(std::type_index(typeid(T)));
322 
323  bool serviceFound =
324  serviceIt != m_RegisteredServices.end() &&
325  !serviceIt->second.empty();
326 
327  if constexpr (!nothrow)
328  solinject_assert(serviceFound);
329 
330  if (!serviceFound)
331  if constexpr (nothrow)
332  return nullptr;
333  else
334  throw exc::ServiceNotRegisteredException(typeid(T));
335 
336  auto& services = serviceIt->second;
337 
338  return GetServiceInstance<T>(*services.rbegin(), container);
339  }
340  };
341 }
sol::di::impl::RegisteredServices::RegisteredServicesMap
std::map< std::type_index, std::vector< DIServicePtr > > RegisteredServicesMap
Map of registered DI services.
Definition: RegisteredServices.hpp:66
solinject_assert
#define solinject_assert(expression)
assert() macro, which is disabled in tests project.
Definition: Defines.hpp:34
std::shared_ptr
sol::di::impl::RegisteredServices::Merge
void Merge(RegisteredServices other)
Merges other RegisteredServices instance into this instance.
Definition: RegisteredServices.hpp:119
sol::di::Container
Dependency Injection container.
Definition: Container.hpp:48
sol::di::impl::RegisteredServices::RegisteredServices
RegisteredServices(RegisteredServicesMap services)
Constructor.
Definition: RegisteredServices.hpp:75
std::move
T move(T... args)
std::vector::reserve
T reserve(T... args)
sol::di::impl::RegisteredServices::RegisterSingletonService
void RegisterSingletonService(ServicePtr< T > instance)
Registers a service with singleton lifetime.
Definition: RegisteredServices.hpp:147
std::vector
std::vector::size
T size(T... args)
std::back_inserter
T back_inserter(T... args)
std::type_index
sol::di::impl::RegisteredServices::GetServices
std::vector< ServicePtr< T > > GetServices(const Container &container) const
Resolves services.
Definition: RegisteredServices.hpp:220
sol::di::impl::RegisteredServices
Registered DI services collection.
Definition: RegisteredServices.hpp:45
solinject_req_assert
#define solinject_req_assert(expression)
Required assert, which is disabled only when the assert() macro from assert.h is disabled.
Definition: Defines.hpp:41
sol::di::impl::RegisteredServices::RegisteredServices
RegisteredServices(const RegisteredServices &other)
Copy constructor.
Definition: RegisteredServices.hpp:81
sol::di::impl::RegisteredServices::RegisterSharedService
void RegisterSharedService(Factory< T > factory)
Registers a service with shared lifetime.
Definition: RegisteredServices.hpp:169
sol::di::impl::RegisteredServices::GetRequiredService
ServicePtr< T > GetRequiredService(const Container &container) const
Resolves a required service.
Definition: RegisteredServices.hpp:194
SingletonService.hpp
ScopedService.hpp
sol::di::impl::RegisteredServices::RegisteredServices
RegisteredServices()
Default constructor.
Definition: RegisteredServices.hpp:69
ServiceNotRegisteredException.hpp
sol::di::impl::RegisteredServices::GetService
ServicePtr< T > GetService(const Container &container) const
Resolves an optional service.
Definition: RegisteredServices.hpp:207
sol::di::impl::RegisteredServices::operator=
RegisteredServices & operator=(RegisteredServices &&other)
Move-assignment operator.
Definition: RegisteredServices.hpp:100
sol::di::impl::RegisteredServices::RegisteredServices
RegisteredServices(RegisteredServices &&other)
Move constructor.
Definition: RegisteredServices.hpp:87
IServiceTyped.hpp
sol::di::impl::RegisteredServices::ServicePtr
typename IServiceTyped< T >::ServicePtr ServicePtr
Pointer to an instance of a service.
Definition: RegisteredServices.hpp:60
Utils.hpp
std::map< std::type_index, std::vector< DIServicePtr > >
std::transform
T transform(T... args)
sol::di::impl::IServiceTyped::ServicePtr
typename std::shared_ptr< T > ServicePtr
Pointer to an instance of a service.
Definition: IServiceTyped.hpp:36
sol::di::impl::RegisteredServices::RegisterTransientService
void RegisterTransientService(Factory< T > factory)
Registers a service with transient lifetime.
Definition: RegisteredServices.hpp:158
sol::di::impl::RegisteredServices::Factory
typename IServiceTyped< T >::Factory Factory
Factory function that accepts a reference to a DI container and returns a pointer to an instance of a...
Definition: RegisteredServices.hpp:53
sol::di::impl::RegisteredServices::RegisterSingletonService
void RegisterSingletonService(Factory< T > factory)
Registers a service with singleton lifetime.
Definition: RegisteredServices.hpp:136
std::swap
T swap(T... args)
TransientService.hpp
sol::di::impl::RegisteredServices::swap
friend void swap(RegisteredServices &a, RegisteredServices &b)
Swaps two RegisteredServices instances.
Definition: RegisteredServices.hpp:107
sol::di::impl::RegisteredServices::DIServicePtr
std::shared_ptr< IService > DIServicePtr
Pointer to a DI service instance.
Definition: RegisteredServices.hpp:63
std::vector::begin
T begin(T... args)
sol::di::impl::RegisteredServices::operator=
RegisteredServices & operator=(RegisteredServices other)
Copy-assignment operator.
Definition: RegisteredServices.hpp:93
std
sol::di::impl::IServiceTyped::Factory
typename std::function< ServicePtr(const Container &)> Factory
Factory function that accepts a reference to a DI container and returns a pointer to an instance of a...
Definition: IServiceTyped.hpp:42
IService.hpp
std::vector::end
T end(T... args)
SharedService.hpp
sol::di::impl::RegisteredServices::RegisterService
void RegisterService(std::type_index type, DIServicePtr diService)
Registers a service.
Definition: RegisteredServices.hpp:181
Defines.hpp