From b5ba23b4f28602ecc6711bc5cbb798346fc89730 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Fri, 12 Jan 2024 15:16:58 +0100 Subject: [PATCH 01/45] code refactor --- CMakeLists.txt | 2 +- Include/SevenBit/DI/CmakeDef.hpp | 2 +- .../DI/Details/Containers/Impl/ServiceInstancesMap.hpp | 2 +- Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp | 2 +- Include/SevenBit/DI/Details/Utils/IsInPlaceObject.hpp | 10 ++++------ README.md | 1 + 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05318e8..baa7473 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15.0) set(_7BIT_DI_LIBRARY 7bitDI) set(_7BIT_DI_VERSION_MAJOR 2) -set(_7BIT_DI_VERSION_MINOR 0) +set(_7BIT_DI_VERSION_MINOR 1) set(_7BIT_DI_VERSION_PATCH 0) set(_7BIT_DI_VERSION ${_7BIT_DI_VERSION_MAJOR}.${_7BIT_DI_VERSION_MINOR}.${_7BIT_DI_VERSION_PATCH}) diff --git a/Include/SevenBit/DI/CmakeDef.hpp b/Include/SevenBit/DI/CmakeDef.hpp index 18bf2f0..fc14090 100644 --- a/Include/SevenBit/DI/CmakeDef.hpp +++ b/Include/SevenBit/DI/CmakeDef.hpp @@ -13,5 +13,5 @@ #endif #define _7BIT_DI_VERSION_MAJOR 2 -/* #undef _7BIT_DI_VERSION_MINOR */ +#define _7BIT_DI_VERSION_MINOR 1 /* #undef _7BIT_DI_VERSION_PATCH */ diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index 466e3c9..9986a30 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -28,7 +28,7 @@ namespace sb::di::details::containers INLINE ServiceInstanceList *ServiceInstancesMap::findServices(const TypeId serviceTypeId) { - auto it = _serviceListMap.find(serviceTypeId); + const auto it = _serviceListMap.find(serviceTypeId); return it != _serviceListMap.end() ? &it->second : nullptr; } diff --git a/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp b/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp index 0569de5..0cc90d4 100644 --- a/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp +++ b/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp @@ -29,7 +29,7 @@ namespace sb::di::details::utils { static_assert( details::utils::notSupportedType, - "Proper constructor for cpecified type was not found, reached maximum constructor params number " + "Proper constructor for specified type was not found, reached maximum constructor params number " "limit, to bump limit define macro _7BIT_DI_CTOR_PARAMS_LIMIT with new value befor including lib"); return 0; } diff --git a/Include/SevenBit/DI/Details/Utils/IsInPlaceObject.hpp b/Include/SevenBit/DI/Details/Utils/IsInPlaceObject.hpp index 3853413..47b55bc 100644 --- a/Include/SevenBit/DI/Details/Utils/IsInPlaceObject.hpp +++ b/Include/SevenBit/DI/Details/Utils/IsInPlaceObject.hpp @@ -8,18 +8,16 @@ namespace sb::di::details::utils { template struct IsInPlaceObject - : std::integral_constant || std::is_array_v || std::is_enum_v || - std::is_class_v)&&!std::is_pointer_v && - !std::is_reference_v> + : std::bool_constant && !std::is_reference_v && + (std::is_arithmetic_v || std::is_array_v || std::is_enum_v || std::is_class_v)> { }; template inline constexpr bool IsInPlaceObjectV = IsInPlaceObject::value; template - struct IsInPlaceObjectConstructable - : std::integral_constant && - (std::is_move_constructible_v || std::is_copy_constructible_v)> + struct IsInPlaceObjectConstructable : std::bool_constant && (std::is_move_constructible_v || + std::is_copy_constructible_v)> { }; diff --git a/README.md b/README.md index f7a9c83..1c92cf4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Linux](https://github.com/7bitcoder/7bitDI/actions/workflows/Linux.yml/badge.svg)](https://github.com/7bitcoder/7bitDI/actions/workflows/Linux.yml) [![Windows](https://github.com/7bitcoder/7bitDI/actions/workflows/Windows.yml/badge.svg)](https://github.com/7bitcoder/7bitDI/actions/workflows/Windows.yml) [![MacOs](https://github.com/7bitcoder/7bitDI/actions/workflows/MacOs.yml/badge.svg)](https://github.com/7bitcoder/7bitDI/actions/workflows/MacOs.yml) +[![Conan Center](https://img.shields.io/conan/v/7bitdi)](https://conan.io/center/recipes/7bitdi)
logo From 9eeba2b208bd3aa2970c9cd5871cd5e53613991c Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 13 Jan 2024 14:33:31 +0100 Subject: [PATCH 02/45] add external service factory --- .../Factories/ExternalServiceFcnFactory.hpp | 59 +++++++++++++++++++ .../Details/Factories/ServiceFcnFactory.hpp | 11 ++-- .../SevenBit/DI/Details/Utils/IsUniquePtr.hpp | 1 + Include/SevenBit/DI/ServiceDescriber.hpp | 56 +++++++++--------- 4 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp new file mode 100644 index 0000000..e610aec --- /dev/null +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" +#include "SevenBit/DI/Details/Services/UniquePtrService.hpp" +#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" +#include "SevenBit/DI/IServiceFactory.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di::details::factories +{ + template class ServiceFcnFactory final : public IServiceFactory + { + using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; + using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; + + mutable FactoryFcn _factoryFunction; + + public: + explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} {} + + [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } + + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + { + ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; + if constexpr (IsUniquePtr::value) + { + return std::make_unique>(invoker.invoke()); + } + else if (IsPtr::value) + { + return std::make_unique>(invoker.invoke()); + } + else if (utils::IsInPlaceObjectConstructableV) + { + if (inPlaceRequest) + { + return std::make_unique>(invoker.invoke()); + } + auto servicePtr = std::make_unique(invoker.invoke()); + return std::make_unique>(std::move(servicePtr)); + } + else + { + static_assert(utils::notSupportedType, + "Service factory return type must be pointer or std::unique_ptr or " + "movable/copyable object"); + } + } + }; +} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index 6aaf9c3..2be5805 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -20,17 +20,18 @@ namespace sb::di::details::factories { using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; - using IsUniquePtr = utils::IsUniquePtr; - using TService = typename IsUniquePtr::Type; + + using IsRetUniquePtr = utils::IsUniquePtr; + using IsRetInPlaceObjectConstructable = utils::IsInPlaceObjectConstructable; mutable FactoryFcn _factoryFunction; public: - using ServiceType = TService; + using ServiceType = std::conditional_t; explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} { - static_assert(IsUniquePtr::value || utils::IsInPlaceObjectConstructableV || + static_assert(IsRetUniquePtr::value || IsRetInPlaceObjectConstructable::value || utils::notSupportedType, "Service factory return type must be std::unique_ptr or movable/copyable object"); } @@ -40,7 +41,7 @@ namespace sb::di::details::factories IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - if constexpr (IsUniquePtr::value) + if constexpr (IsRetUniquePtr::value) { return std::make_unique>(invoker.invoke()); } diff --git a/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp b/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp index 8e30ed5..9c22b25 100644 --- a/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp +++ b/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp @@ -19,4 +19,5 @@ namespace sb::di::details::utils template inline constexpr bool IsUniquePtrV = IsUniquePtr::value; + template using IsUniquePtrT = typename IsUniquePtr::Type; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 24f1a1b..95dbbf4 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -7,6 +7,7 @@ #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" +#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" @@ -228,6 +229,33 @@ namespace sb::di return describeFrom(ServiceLifeTime::transient(), std::forward(factory)); } + /** + * @brief Creates service descriptor + * @details Creates service descriptor with: + * lifetime - given service lifetime, + * serviceTypeId - typeid(TService), + * implementationTypeId - extracted from factory return type, + * factory - default factory using FactoryFcn factory functor + * @tparam TService base service type + * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> + * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, + * vectors with pointers or unique pointers, implementation type must inherit from TService + * + * Example: + * @code{.cpp} + * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( + * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); + * @endcode + */ + template + static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) + { + using FactoryType = details::factories::ServiceFcnFactory; + details::utils::Assert::inheritance(); + auto factory = std::make_unique(std::forward(factoryFcn)); + return {typeid(TService), lifetime, std::move(factory)}; + } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -311,36 +339,10 @@ namespace sb::di */ template static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) - { - return describeFrom(lifetime, std::forward(factoryFcn)); - } - - /** - * @brief Creates service descriptor - * @details Creates service descriptor with: - * lifetime - given service lifetime, - * serviceTypeId - typeid(TService), - * implementationTypeId - extracted from factory return type, - * factory - default factory using FactoryFcn factory functor - * @tparam TService base service type - * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> - * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers, implementation type must inherit from TService - * - * Example: - * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( - * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); - * @endcode - */ - template - static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) { using FactoryType = details::factories::ServiceFcnFactory; auto factory = std::make_unique(std::forward(factoryFcn)); - - using Service = std::conditional_t, typename FactoryType::ServiceType, TService>; - return {typeid(Service), lifetime, std::move(factory)}; + return {factory->getServiceTypeId(), lifetime, std::move(factory)}; } }; } // namespace sb::di From 3a6dc8945e5dd2c4a8812c6f000e2b79d1367267 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 14 Jan 2024 18:26:36 +0100 Subject: [PATCH 03/45] add unique ptr service fcn factory --- Docs/conf.py | 2 +- .../Factories/ExternalServiceFcnFactory.hpp | 38 ++---- .../Details/Factories/ServiceFcnFactory.hpp | 28 ++--- .../Factories/UniquePtrServiceFcnFactory.hpp | 42 +++++++ Include/SevenBit/DI/Details/Utils/IsPtr.hpp | 14 +++ .../SevenBit/DI/Details/Utils/IsUniquePtr.hpp | 3 - .../SevenBit/DI/Details/Utils/RemovePtr.hpp | 13 ++ .../DI/Details/Utils/RemoveUniquePtr.hpp | 21 ++++ Include/SevenBit/DI/ServiceDescriber.hpp | 119 +++++++++++++----- .../Unit/Factories/ServiceFcnFactoryTest.cpp | 18 +-- 10 files changed, 203 insertions(+), 95 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp create mode 100644 Include/SevenBit/DI/Details/Utils/IsPtr.hpp create mode 100644 Include/SevenBit/DI/Details/Utils/RemovePtr.hpp create mode 100644 Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp diff --git a/Docs/conf.py b/Docs/conf.py index badb26d..4ac3223 100644 --- a/Docs/conf.py +++ b/Docs/conf.py @@ -13,7 +13,7 @@ def createIfNotExists(path): project = "7bitDI" copyright = "2023, 7BitCoder Sylwester Dawida" author = "Sylwester Dawida" -version = "2.0.0" +version = "2.1.0" extensions = [ "sphinx.ext.autodoc", diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp index e610aec..9c6f1b3 100644 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp @@ -6,9 +6,10 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" -#include "SevenBit/DI/Details/Services/InPlaceService.hpp" +#include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" -#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" +#include "SevenBit/DI/Details/Utils/IsPtr.hpp" +#include "SevenBit/DI/Details/Utils/RemovePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceProvider.hpp" @@ -16,44 +17,27 @@ namespace sb::di::details::factories { - template class ServiceFcnFactory final : public IServiceFactory + template class ExternalServiceFcnFactory final : public IServiceFactory { using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; + using ServiceType = utils::RemovePtrT; mutable FactoryFcn _factoryFunction; public: - explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} {} + explicit ExternalServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} + { + static_assert(utils::IsPtrV || utils::notSupportedType, + "Service factory return type must be pointer"); + } [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - if constexpr (IsUniquePtr::value) - { - return std::make_unique>(invoker.invoke()); - } - else if (IsPtr::value) - { - return std::make_unique>(invoker.invoke()); - } - else if (utils::IsInPlaceObjectConstructableV) - { - if (inPlaceRequest) - { - return std::make_unique>(invoker.invoke()); - } - auto servicePtr = std::make_unique(invoker.invoke()); - return std::make_unique>(std::move(servicePtr)); - } - else - { - static_assert(utils::notSupportedType, - "Service factory return type must be pointer or std::unique_ptr or " - "movable/copyable object"); - } + return std::make_unique>(invoker.invoke()); } }; } // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index 2be5805..a2f150c 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -8,10 +8,8 @@ #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" -#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" #include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -21,39 +19,27 @@ namespace sb::di::details::factories using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; - using IsRetUniquePtr = utils::IsUniquePtr; - using IsRetInPlaceObjectConstructable = utils::IsInPlaceObjectConstructable; - mutable FactoryFcn _factoryFunction; public: - using ServiceType = std::conditional_t; - explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} { - static_assert(IsRetUniquePtr::value || IsRetInPlaceObjectConstructable::value || + static_assert(utils::IsInPlaceObjectConstructableV || utils::notSupportedType, - "Service factory return type must be std::unique_ptr or movable/copyable object"); + "Service factory return type must be copyable or movable"); } - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } + [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(FactoryReturnType); } IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - if constexpr (IsRetUniquePtr::value) - { - return std::make_unique>(invoker.invoke()); - } - else + if (inPlaceRequest) { - if (inPlaceRequest) - { - return std::make_unique>(invoker.invoke()); - } - auto servicePtr = std::make_unique(invoker.invoke()); - return std::make_unique>(std::move(servicePtr)); + return std::make_unique>(invoker.invoke()); } + auto servicePtr = std::make_unique(invoker.invoke()); + return std::make_unique>(std::move(servicePtr)); } }; } // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp new file mode 100644 index 0000000..227fd8c --- /dev/null +++ b/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" +#include "SevenBit/DI/Details/Services/UniquePtrService.hpp" +#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" +#include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" +#include "SevenBit/DI/IServiceFactory.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di::details::factories +{ + template class UniquePtrServiceFcnFactory final : public IServiceFactory + { + using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; + using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; + using ServiceType = utils::RemoveUniquePtrT; + + mutable FactoryFcn _factoryFunction; + + public: + explicit UniquePtrServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} + { + static_assert(utils::IsUniquePtrV || utils::notSupportedType, + "Service factory return type must be std::unique_ptr"); + } + + [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } + + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + { + ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; + return std::make_unique>(invoker.invoke()); + } + }; +} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Utils/IsPtr.hpp b/Include/SevenBit/DI/Details/Utils/IsPtr.hpp new file mode 100644 index 0000000..8dbcb34 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/IsPtr.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + template using IsPtr = std::is_pointer; + + template inline constexpr bool IsPtrV = IsPtr::value; + +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp b/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp index 9c22b25..9cc1d7e 100644 --- a/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp +++ b/Include/SevenBit/DI/Details/Utils/IsUniquePtr.hpp @@ -9,15 +9,12 @@ namespace sb::di::details::utils { template struct IsUniquePtr : std::false_type { - using Type = T; }; template struct IsUniquePtr> : std::true_type { - using Type = T; }; template inline constexpr bool IsUniquePtrV = IsUniquePtr::value; - template using IsUniquePtrT = typename IsUniquePtr::Type; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp b/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp new file mode 100644 index 0000000..77cf2be --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + template using RemovePtr = std::remove_pointer; + + template using RemovePtrT = RemovePtr::type; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp b/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp new file mode 100644 index 0000000..2bf6e56 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + template struct RemoveUniquePtr + { + using Type = T; + }; + + template struct RemoveUniquePtr> + { + using Type = T; + }; + + template using RemoveUniquePtrT = typename RemoveUniquePtr::Type; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 95dbbf4..2a38c14 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -5,10 +5,15 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" +#include "SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" +#include "SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" +#include "SevenBit/DI/Details/Utils/IsInPlaceObject.hpp" +#include "SevenBit/DI/Details/Utils/IsPtr.hpp" +#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" @@ -226,34 +231,8 @@ namespace sb::di */ template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::transient(), std::forward(factory)); - } - - /** - * @brief Creates service descriptor - * @details Creates service descriptor with: - * lifetime - given service lifetime, - * serviceTypeId - typeid(TService), - * implementationTypeId - extracted from factory return type, - * factory - default factory using FactoryFcn factory functor - * @tparam TService base service type - * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> - * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers, implementation type must inherit from TService - * - * Example: - * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( - * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); - * @endcode - */ - template - static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) - { - using FactoryType = details::factories::ServiceFcnFactory; - details::utils::Assert::inheritance(); - auto factory = std::make_unique(std::forward(factoryFcn)); - return {typeid(TService), lifetime, std::move(factory)}; + return describeFrom(ServiceLifeTime::transient(), + std::forward(factory)); } /** @@ -275,8 +254,10 @@ namespace sb::di */ template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::singleton(), std::forward(factory)); + return describeFrom(ServiceLifeTime::singleton(), + std::forward(factory)); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -294,9 +275,10 @@ namespace sb::di * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ + template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::scoped(), std::forward(factory)); + return describeFrom(ServiceLifeTime::scoped(), std::forward(factory)); } /** * @brief Creates service descriptor @@ -315,9 +297,11 @@ namespace sb::di * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ + template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::transient(), std::forward(factory)); + return describeFrom(ServiceLifeTime::transient(), + std::forward(factory)); } /** @@ -340,9 +324,76 @@ namespace sb::di template static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) { - using FactoryType = details::factories::ServiceFcnFactory; - auto factory = std::make_unique(std::forward(factoryFcn)); - return {factory->getServiceTypeId(), lifetime, std::move(factory)}; + return describeFrom(lifetime, std::forward(factoryFcn)); + } + + /** + * @brief Creates service descriptor + * @details Creates service descriptor with: + * lifetime - given service lifetime, + * serviceTypeId - typeid(TService), + * implementationTypeId - extracted from factory return type, + * factory - default factory using FactoryFcn factory functor + * @tparam TService base service type + * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> + * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, + * vectors with pointers or unique pointers, implementation type must inherit from TService + * + * Example: + * @code{.cpp} + * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( + * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); + * @endcode + */ + template + static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) + { + return describeFrom(lifetime, std::forward(factoryFcn)); + } + + private: + template + static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) + { + auto factory = makeFactoryFrom(lifetime, std::forward(factoryFcn)); + auto serviceTypeId = std::is_void_v ? factory->getServiceTypeId() : TypeId(typeid(TService)); + return {serviceTypeId, lifetime, std::move(factory)}; + } + + template + static IServiceFactory::Ptr makeFactoryFrom(const ServiceLifeTime &lifetime, FactoryFcn &&factoryFcn) + { + using ReturnType = typename details::helpers::ServiceFactoryInvoker::ReturnType; + if constexpr (details::utils::IsUniquePtrV) + { + return std::make_unique>( + std::forward(factoryFcn)); + } + else if constexpr (details::utils::IsInPlaceObjectConstructableV) + { + return std::make_unique>( + std::forward(factoryFcn)); + } + else if constexpr (details::utils::IsPtrV && !AssumeTransient) + { + if (lifetime.isTransient()) + { + throw ""; + } + return std::make_unique>( + std::forward(factoryFcn)); + } + else + { + notSupportedReturnType(); + } + } + + template static void notSupportedReturnType() + { + static_assert(details::utils::notSupportedType, + "Service factory return type must be std::unique_ptr or movable/copyable object or " + "pointer for non transient services"); } }; } // namespace sb::di diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index 2cf5034..a48bcc1 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -41,8 +41,8 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateService) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); + // EXPECT_TRUE(dynamic_cast *>(instance.get())); + // EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -264,9 +264,9 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq2Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - EXPECT_TRUE( - dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); + // EXPECT_TRUE( + // dynamic_cast *>(instance.get())); + // EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -310,8 +310,8 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); + // EXPECT_TRUE(dynamic_cast + // *>(instance.get())); EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -358,7 +358,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); + // EXPECT_TRUE(dynamic_cast + // *>(instance.get())); EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } From 1e1789a6d3271dc705944c3179bd2a66405b9534 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 14 Jan 2024 19:49:12 +0100 Subject: [PATCH 04/45] fix build --- .../Factories/ExternalServiceFcnFactory.hpp | 1 - .../SevenBit/DI/Details/Utils/RemovePtr.hpp | 2 +- Include/SevenBit/DI/ServiceDescriber.hpp | 26 ++++++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp index 9c6f1b3..48f9158 100644 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" -#include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/Details/Utils/IsPtr.hpp" #include "SevenBit/DI/Details/Utils/RemovePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" diff --git a/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp b/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp index 77cf2be..7633c7e 100644 --- a/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp +++ b/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp @@ -9,5 +9,5 @@ namespace sb::di::details::utils { template using RemovePtr = std::remove_pointer; - template using RemovePtrT = RemovePtr::type; + template using RemovePtrT = typename RemovePtr::type; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 2a38c14..805cdf8 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -187,7 +187,8 @@ namespace sb::di */ template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::singleton(), std::forward(factory)); + return describeFrom(ServiceLifeTime::singleton(), + std::forward(factory)); } /** * @brief Creates service descriptor @@ -209,7 +210,8 @@ namespace sb::di */ template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::scoped(), std::forward(factory)); + return describeFrom(ServiceLifeTime::scoped(), + std::forward(factory)); } /** * @brief Creates service descriptor @@ -364,23 +366,23 @@ namespace sb::di static IServiceFactory::Ptr makeFactoryFrom(const ServiceLifeTime &lifetime, FactoryFcn &&factoryFcn) { using ReturnType = typename details::helpers::ServiceFactoryInvoker::ReturnType; - if constexpr (details::utils::IsUniquePtrV) + if constexpr (details::utils::IsPtrV && !AssumeTransient) { - return std::make_unique>( + if (lifetime.isTransient()) + { + throw InjectorException("Service factory cannot return pointer for transient service"); + } + return std::make_unique>( std::forward(factoryFcn)); } - else if constexpr (details::utils::IsInPlaceObjectConstructableV) + else if constexpr (details::utils::IsUniquePtrV) { - return std::make_unique>( + return std::make_unique>( std::forward(factoryFcn)); } - else if constexpr (details::utils::IsPtrV && !AssumeTransient) + else if constexpr (details::utils::IsInPlaceObjectConstructableV) { - if (lifetime.isTransient()) - { - throw ""; - } - return std::make_unique>( + return std::make_unique>( std::forward(factoryFcn)); } else From 4cba698fe78406036fd525c36c553daaa047dd8d Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 20 Jan 2024 16:14:21 +0100 Subject: [PATCH 05/45] add enum check --- Include/SevenBit/DI/Details/Utils/Require.hpp | 9 +++++++++ Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 3 ++- Include/SevenBit/DI/ServiceLifeTime.hpp | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index d790d59..70e7985 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -52,6 +52,15 @@ namespace sb::di::details::utils } } + template static void validEnum(TEnum value) + { + if (value < 0 || value >= TEnum::Count) + { + throw InjectorException{"enum value: " + std::to_string(value) + " is invalid, shoud be in range [0" + + std::to_string(TEnum::Count) + "]"}; + } + } + static IServiceInstance::Ptr validInstanceAndGet(IServiceInstance::Ptr &&instance); static IServiceInstance &validInstanceAndGet(IServiceInstance *instance); diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp index 42acfb1..4aba3e7 100644 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp @@ -2,6 +2,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" namespace sb::di @@ -10,7 +11,7 @@ namespace sb::di INLINE ServiceLifeTime ServiceLifeTime::scoped() { return ServiceLifeTime{Scoped}; } INLINE ServiceLifeTime ServiceLifeTime::transient() { return ServiceLifeTime{Transient}; } - INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(type) {} + INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(type) { details::utils::Require::validEnum(type); } INLINE bool ServiceLifeTime::isSingleton() const { return is(Singleton); } INLINE bool ServiceLifeTime::isScoped() const { return is(Scoped); } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index ef23181..3b722a7 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -14,7 +14,9 @@ namespace sb::di { Singleton, Scoped, - Transient + Transient, + + Count }; private: From 55f6e764b62f60eaf29563e367ec808acd4c80b9 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 20 Jan 2024 18:29:01 +0100 Subject: [PATCH 06/45] add alias to service lifetime --- .../Details/Core/Impl/ServiceInstanceProvider.hpp | 6 +++--- Include/SevenBit/DI/Details/Utils/Check.hpp | 12 ++++++++++++ Include/SevenBit/DI/Details/Utils/Impl/Check.hpp | 5 ++++- Include/SevenBit/DI/Details/Utils/Impl/Require.hpp | 2 +- Include/SevenBit/DI/Details/Utils/Require.hpp | 13 ++++++++++--- Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 5 +++-- Include/SevenBit/DI/ServiceLifeTime.hpp | 12 ++++++++---- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index bc05102..46f9fc7 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -59,7 +59,7 @@ namespace sb::di::details::core return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; } - INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(TypeId serviceTypeId) + INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { const auto instances = findRegisteredInstances(serviceTypeId); if (!instances) @@ -98,7 +98,7 @@ namespace sb::di::details::core return descriptors ? tryCreateAll(*descriptors) : std::nullopt; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(TypeId serviceTypeId) + INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) { if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) { @@ -109,7 +109,7 @@ namespace sb::di::details::core "registered as singleton/scoped instance"}; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(TypeId serviceTypeId) + INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId); descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index c32cd7f..5b7fa2a 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include "SevenBit/DI/LibraryConfig.hpp" @@ -8,6 +9,17 @@ namespace sb::di::details::utils { struct EXPORT Check { + template static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } + + template static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } + + template static bool notNull(const T *ptr) { return ptr != nullptr; } + + template static bool enumValidity(TEnum value) + { + return std::is_enum_v && value >= 0 && value < TEnum::Count; + } + static bool instanceValidity(const IServiceInstance::Ptr &instance); static bool instanceValidity(const IServiceInstance *instance); diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp index fb1821f..3bf6d15 100644 --- a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp @@ -11,5 +11,8 @@ namespace sb::di::details::utils return instanceValidity(instance.get()); } - INLINE bool Check::instanceValidity(const IServiceInstance *instance) { return instance && instance->isValid(); } + INLINE bool Check::instanceValidity(const IServiceInstance *instance) + { + return notNull(instance) && instance->isValid(); + } } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp index 8ccb0ed..aad86a8 100644 --- a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp @@ -24,7 +24,7 @@ namespace sb::di::details::utils INLINE void Require::validInstance(const IServiceInstance *instance) { notNull(instance); - if (!instance->isValid()) + if (!Check::instanceValidity(instance)) { throw InvalidServiceException{instance->getTypeId()}; } diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index 70e7985..5da8886 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -4,6 +4,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/IServiceInstance.hpp" @@ -43,7 +44,7 @@ namespace sb::di::details::utils template static void notNull(const T *ptr, const std::string_view failMessage = "") { - if (!ptr) + if (!Check::notNull(ptr)) { const auto message = !failMessage.empty() ? std::string{failMessage} @@ -52,12 +53,18 @@ namespace sb::di::details::utils } } + template static TEnum validEnumAndGet(TEnum value) + { + validEnum(value); + return value; + } + template static void validEnum(TEnum value) { - if (value < 0 || value >= TEnum::Count) + if (!Check::enumValidity(value)) { throw InjectorException{"enum value: " + std::to_string(value) + " is invalid, shoud be in range [0" + - std::to_string(TEnum::Count) + "]"}; + std::to_string(TEnum::Count) + ")"}; } } diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp index 4aba3e7..a629a25 100644 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp @@ -11,12 +11,13 @@ namespace sb::di INLINE ServiceLifeTime ServiceLifeTime::scoped() { return ServiceLifeTime{Scoped}; } INLINE ServiceLifeTime ServiceLifeTime::transient() { return ServiceLifeTime{Transient}; } - INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(type) { details::utils::Require::validEnum(type); } + INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} + INLINE bool ServiceLifeTime::is(const Type type) const { return _type == type; } INLINE bool ServiceLifeTime::isSingleton() const { return is(Singleton); } INLINE bool ServiceLifeTime::isScoped() const { return is(Scoped); } INLINE bool ServiceLifeTime::isTransient() const { return is(Transient); } - INLINE bool ServiceLifeTime::is(const Type type) const { return _type == type; } + INLINE bool ServiceLifeTime::isAlias() const { return is(Alias); } INLINE bool ServiceLifeTime::operator==(const ServiceLifeTime &scope) const { return _type == scope._type; } INLINE bool ServiceLifeTime::operator!=(const ServiceLifeTime &scope) const { return _type != scope._type; } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index 3b722a7..fcccc4f 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -8,13 +8,14 @@ namespace sb::di { public: /** - * @brief 3 types of available service lifetimes + * @brief 4 types of available service lifetimes */ enum Type { Singleton, Scoped, Transient, + Alias, Count }; @@ -47,6 +48,10 @@ namespace sb::di ServiceLifeTime &operator=(ServiceLifeTime &&) = default; ServiceLifeTime &operator=(const ServiceLifeTime &) = default; + /** + * @brief checks if lifetime is given type + */ + [[nodiscard]] bool is(Type type) const; /** * @brief checks if lifetime is singleton */ @@ -59,11 +64,10 @@ namespace sb::di * @brief checks if lifetime is transient */ [[nodiscard]] bool isTransient() const; - /** - * @brief checks if lifetime is given type + * @brief checks if lifetime is alias */ - [[nodiscard]] bool is(Type type) const; + [[nodiscard]] bool isAlias() const; bool operator!=(const ServiceLifeTime &scope) const; bool operator==(const ServiceLifeTime &scope) const; From f1c184d54eff6e14450f800f65f4847682b54387 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 21 Jan 2024 15:10:21 +0100 Subject: [PATCH 07/45] code refactor --- .../Core/Impl/ServiceInstanceCreator.hpp | 219 ++++++++++++++++++ .../Core/Impl/ServiceInstanceProvider.hpp | 1 + .../Details/Core/ServiceInstanceCreator.hpp | 46 ++++ Include/SevenBit/DI/IServiceFactory.hpp | 3 +- Source/Source.cpp | 1 + 5 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp create mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp new file mode 100644 index 0000000..43fb4ff --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -0,0 +1,219 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include "SevenBit/DI/Details/Services/ExternalService.hpp" +#include "SevenBit/DI/Details/Utils/Check.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceProviderOptions.hpp" + +namespace sb::di::details::core +{ + INLINE ServiceInstanceCreator::ServiceInstanceCreator(const ServiceInstanceCreator &provider) + : _options(provider._options), _root(provider._root), _scoped(_options.strongDestructionOrder) + { + } + + INLINE ServiceInstanceCreator::ServiceInstanceCreator(ServiceInstanceCreatorRoot &root, + ServiceProviderOptions options) + : _options(options), _root(root), _scoped(_options.strongDestructionOrder) + { + } + + INLINE void ServiceInstanceCreator::init(ServiceProvider &serviceProvider) + { + _serviceProvider = &serviceProvider; + auto external = std::make_unique>(_serviceProvider); + _scoped.insert(typeid(ServiceProvider), std::move(external)).seal(); + } + + INLINE IServiceInstanceCreator::Ptr ServiceInstanceCreator::createScope() const + { + return IServiceInstanceCreator::Ptr{new ServiceInstanceCreator{*this}}; + } + + INLINE const IServiceInstance &ServiceInstanceCreator::getInstance(const TypeId serviceTypeId) + { + if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::instanceValidity(instance)) + { + return *instance; + } + throw ServiceNotFoundException{serviceTypeId, + "Service was not registered or was registered as transient instance"}; + } + + INLINE const IServiceInstance *ServiceInstanceCreator::tryGetInstance(const TypeId serviceTypeId) + { + if (const auto instances = findRegisteredInstances(serviceTypeId)) + { + return instances->last().get(); + } + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; + } + + INLINE const OneOrList *ServiceInstanceCreator::tryGetInstances(const TypeId serviceTypeId) + { + const auto instances = findRegisteredInstances(serviceTypeId); + if (!instances) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; + } + if (!instances->isSealed()) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? &createRestInstances(*descriptors, *instances, true) : nullptr; + } + return &instances->getInnerList(); + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const TypeId serviceTypeId) + { + if (auto instance = tryCreateInstance(serviceTypeId); utils::Check::instanceValidity(instance)) + { + return instance; + } + throw ServiceNotFoundException{serviceTypeId, + "Service was not registered or was registered as singleton/scoped instance"}; + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreateInstance(const TypeId serviceTypeId) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreate(descriptors->last(), false) : nullptr; + } + + INLINE std::optional> ServiceInstanceCreator::tryCreateInstances( + TypeId serviceTypeId) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreateAll(*descriptors) : std::nullopt; + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceInPlace(const TypeId serviceTypeId) + { + if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) + { + return instance; + } + throw ServiceNotFoundException{serviceTypeId, + "Service was not registered, typeid does not match implementationId or was " + "registered as singleton/scoped instance"}; + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreateInstanceInPlace(const TypeId serviceTypeId) + { + if (const auto descriptors = findDescriptors(serviceTypeId); + descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) + { + return tryCreate(descriptors->last(), true); + } + return nullptr; + } + + INLINE void ServiceInstanceCreator::clear() { _scoped.clear(); } + + INLINE const IServiceInstance *ServiceInstanceCreator::tryCreateAndRegister( + const containers::ServiceDescriptorList &descriptors) + { + if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) + { + auto &instances = + instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); + if (descriptors.size() == 1) + { + instances.seal(); + } + return instances.last().get(); + } + return nullptr; + } + + INLINE const OneOrList *ServiceInstanceCreator::tryCreateAndRegisterAll( + const containers::ServiceDescriptorList &descriptors) + { + if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) + { + auto &instances = + instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); + return &createRestInstances(descriptors, instances, true); + } + return nullptr; + } + + INLINE OneOrList &ServiceInstanceCreator::createRestInstances( + const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances, + const bool inPlaceRequest) + { + if (descriptors.size() > 1) + { + instances.reserve(descriptors.size()); + auto realFirst = createInstance(descriptors.first(), inPlaceRequest); + const auto end = --descriptors.end(); + for (auto it = ++descriptors.begin(); it != end; ++it) // skip first and last + { + instances.add(createInstance(*it, inPlaceRequest)); + } + instances.add(std::move(realFirst)); + instances.first().swap(instances.last()); + } + instances.seal(); + return instances.getInnerList(); + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreate(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) + { + return descriptor.getLifeTime().isTransient() ? createInstance(descriptor, inPlaceRequest) : nullptr; + } + + INLINE std::optional> ServiceInstanceCreator::tryCreateAll( + const containers::ServiceDescriptorList &descriptors) + { + if (descriptors.getLifeTime().isTransient()) + { + containers::ServiceInstanceList instances{createInstance(descriptors.last(), false)}; + createRestInstances(descriptors, instances, false); + return std::move(instances.getInnerList()); + } + return std::nullopt; + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) + { + if (descriptor.getLifeTime().isSingleton() && this != &_root) + { + return _root.createInstance(descriptor, inPlaceRequest); + } + auto _ = _root.spawnGuard(descriptor.getImplementationTypeId()); + return utils::Require::validInstanceAndGet(descriptor.getImplementationFactory().createInstance( + *utils::Require::notNullAndGet(_serviceProvider), inPlaceRequest)); + } + + INLINE const ServiceProviderOptions &ServiceInstanceCreator::getOptions() const { return _options; } + + INLINE containers::ServiceInstanceList *ServiceInstanceCreator::findRegisteredInstances(const TypeId serviceTypeId) + { + const auto singletons = _root.getSingletons().findServices(serviceTypeId); + return singletons ? singletons : _scoped.findServices(serviceTypeId); + } + + INLINE containers::ServiceInstancesMap *ServiceInstanceCreator::tryGetInstancesMap(const ServiceLifeTime &lifeTime) + { + return lifeTime.isTransient() ? nullptr : (lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped); + } + + INLINE const containers::ServiceDescriptorList *ServiceInstanceCreator::findDescriptors( + const TypeId serviceTypeId) const + { + return _root.getDescriptorsMap().findDescriptors(serviceTypeId); + } +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 46f9fc7..27e0cc7 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -5,6 +5,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp new file mode 100644 index 0000000..b2e0dbb --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" +#include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceDescriptor.hpp" +#include "SevenBit/DI/ServiceLifeTime.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di::details::core +{ + class EXPORT ServiceInstanceCreator + { + ServiceProvider &_provider; + containers::ServiceDescriptorList &_descriptors; + + public: + using Ptr = std::unique_ptr; + + explicit ServiceInstanceCreator(ServiceProvider &provider, containers::ServiceDescriptorList &descriptors); + + const IServiceInstance *tryCreateAndRegister(); + + const OneOrList *tryCreateAndRegisterAll( + const containers::ServiceDescriptorList &descriptors); + + IServiceInstance::Ptr tryCreate(const ServiceDescriptor &descriptor, bool inPlaceRequest); + std::optional> tryCreateAll( + const containers::ServiceDescriptorList &descriptors); + + OneOrList &createRestInstances(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances, + bool inPlaceRequest); + + IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + + containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); + }; +} // namespace sb::di::details::core + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp" +#endif diff --git a/Include/SevenBit/DI/IServiceFactory.hpp b/Include/SevenBit/DI/IServiceFactory.hpp index 1cbb4f7..5df7418 100644 --- a/Include/SevenBit/DI/IServiceFactory.hpp +++ b/Include/SevenBit/DI/IServiceFactory.hpp @@ -5,10 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" namespace sb::di { + class ServiceProvider; + struct IServiceFactory { using Ptr = std::unique_ptr; diff --git a/Source/Source.cpp b/Source/Source.cpp index 2d766d0..79da9a3 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -5,6 +5,7 @@ #include "SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp" #include "SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Details/Helpers/Impl/CircularDependencyGuard.hpp" From 05de74718a938b0ab2e3c04c7eb4a91cb57c9601 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 21 Jan 2024 18:02:52 +0100 Subject: [PATCH 08/45] refactor provider code --- .../Containers/Impl/ServiceInstancesMap.hpp | 9 +- .../Containers/ServiceInstancesMap.hpp | 4 +- .../Core/Impl/ServiceInstanceCreator.hpp | 219 ------------------ .../Core/Impl/ServiceInstanceProvider.hpp | 88 ++----- .../Core/Impl/ServiceInstancesCreator.hpp | 107 +++++++++ .../Details/Core/ServiceInstanceCreator.hpp | 46 ---- .../Details/Core/ServiceInstanceProvider.hpp | 17 +- .../Details/Core/ServiceInstancesCreator.hpp | 59 +++++ 8 files changed, 205 insertions(+), 344 deletions(-) delete mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp create mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp delete mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp create mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index 9986a30..71ca418 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -11,9 +11,14 @@ namespace sb::di::details::containers { } - INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, IServiceInstance::Ptr service) + INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, IServiceInstance::Ptr instance) { - auto [it, inserted] = _serviceListMap.emplace(serviceTypeId, std::move(service)); + return insert(serviceTypeId, ServiceInstanceList{std::move(instance)}); + } + + INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, ServiceInstanceList instances) + { + auto [it, inserted] = _serviceListMap.emplace(serviceTypeId, std::move(instances)); if (inserted && _strongDestructionOrder) { _constructionOrder.push_back(serviceTypeId); diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp index 98da879..b515d75 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp @@ -27,7 +27,9 @@ namespace sb::di::details::containers ServiceInstancesMap &operator=(const ServiceInstancesMap &) = delete; - ServiceInstanceList &insert(TypeId serviceTypeId, IServiceInstance::Ptr service); + ServiceInstanceList &insert(TypeId serviceTypeId, IServiceInstance::Ptr instance); + + ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstanceList instances); [[nodiscard]] bool contains(TypeId serviceTypeId) const; diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp deleted file mode 100644 index 43fb4ff..0000000 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" -#include "SevenBit/DI/Details/Services/ExternalService.hpp" -#include "SevenBit/DI/Details/Utils/Check.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProviderOptions.hpp" - -namespace sb::di::details::core -{ - INLINE ServiceInstanceCreator::ServiceInstanceCreator(const ServiceInstanceCreator &provider) - : _options(provider._options), _root(provider._root), _scoped(_options.strongDestructionOrder) - { - } - - INLINE ServiceInstanceCreator::ServiceInstanceCreator(ServiceInstanceCreatorRoot &root, - ServiceProviderOptions options) - : _options(options), _root(root), _scoped(_options.strongDestructionOrder) - { - } - - INLINE void ServiceInstanceCreator::init(ServiceProvider &serviceProvider) - { - _serviceProvider = &serviceProvider; - auto external = std::make_unique>(_serviceProvider); - _scoped.insert(typeid(ServiceProvider), std::move(external)).seal(); - } - - INLINE IServiceInstanceCreator::Ptr ServiceInstanceCreator::createScope() const - { - return IServiceInstanceCreator::Ptr{new ServiceInstanceCreator{*this}}; - } - - INLINE const IServiceInstance &ServiceInstanceCreator::getInstance(const TypeId serviceTypeId) - { - if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::instanceValidity(instance)) - { - return *instance; - } - throw ServiceNotFoundException{serviceTypeId, - "Service was not registered or was registered as transient instance"}; - } - - INLINE const IServiceInstance *ServiceInstanceCreator::tryGetInstance(const TypeId serviceTypeId) - { - if (const auto instances = findRegisteredInstances(serviceTypeId)) - { - return instances->last().get(); - } - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; - } - - INLINE const OneOrList *ServiceInstanceCreator::tryGetInstances(const TypeId serviceTypeId) - { - const auto instances = findRegisteredInstances(serviceTypeId); - if (!instances) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; - } - if (!instances->isSealed()) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? &createRestInstances(*descriptors, *instances, true) : nullptr; - } - return &instances->getInnerList(); - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const TypeId serviceTypeId) - { - if (auto instance = tryCreateInstance(serviceTypeId); utils::Check::instanceValidity(instance)) - { - return instance; - } - throw ServiceNotFoundException{serviceTypeId, - "Service was not registered or was registered as singleton/scoped instance"}; - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreateInstance(const TypeId serviceTypeId) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreate(descriptors->last(), false) : nullptr; - } - - INLINE std::optional> ServiceInstanceCreator::tryCreateInstances( - TypeId serviceTypeId) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAll(*descriptors) : std::nullopt; - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceInPlace(const TypeId serviceTypeId) - { - if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) - { - return instance; - } - throw ServiceNotFoundException{serviceTypeId, - "Service was not registered, typeid does not match implementationId or was " - "registered as singleton/scoped instance"}; - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreateInstanceInPlace(const TypeId serviceTypeId) - { - if (const auto descriptors = findDescriptors(serviceTypeId); - descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) - { - return tryCreate(descriptors->last(), true); - } - return nullptr; - } - - INLINE void ServiceInstanceCreator::clear() { _scoped.clear(); } - - INLINE const IServiceInstance *ServiceInstanceCreator::tryCreateAndRegister( - const containers::ServiceDescriptorList &descriptors) - { - if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) - { - auto &instances = - instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); - if (descriptors.size() == 1) - { - instances.seal(); - } - return instances.last().get(); - } - return nullptr; - } - - INLINE const OneOrList *ServiceInstanceCreator::tryCreateAndRegisterAll( - const containers::ServiceDescriptorList &descriptors) - { - if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) - { - auto &instances = - instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); - return &createRestInstances(descriptors, instances, true); - } - return nullptr; - } - - INLINE OneOrList &ServiceInstanceCreator::createRestInstances( - const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances, - const bool inPlaceRequest) - { - if (descriptors.size() > 1) - { - instances.reserve(descriptors.size()); - auto realFirst = createInstance(descriptors.first(), inPlaceRequest); - const auto end = --descriptors.end(); - for (auto it = ++descriptors.begin(); it != end; ++it) // skip first and last - { - instances.add(createInstance(*it, inPlaceRequest)); - } - instances.add(std::move(realFirst)); - instances.first().swap(instances.last()); - } - instances.seal(); - return instances.getInnerList(); - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::tryCreate(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) - { - return descriptor.getLifeTime().isTransient() ? createInstance(descriptor, inPlaceRequest) : nullptr; - } - - INLINE std::optional> ServiceInstanceCreator::tryCreateAll( - const containers::ServiceDescriptorList &descriptors) - { - if (descriptors.getLifeTime().isTransient()) - { - containers::ServiceInstanceList instances{createInstance(descriptors.last(), false)}; - createRestInstances(descriptors, instances, false); - return std::move(instances.getInnerList()); - } - return std::nullopt; - } - - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) - { - if (descriptor.getLifeTime().isSingleton() && this != &_root) - { - return _root.createInstance(descriptor, inPlaceRequest); - } - auto _ = _root.spawnGuard(descriptor.getImplementationTypeId()); - return utils::Require::validInstanceAndGet(descriptor.getImplementationFactory().createInstance( - *utils::Require::notNullAndGet(_serviceProvider), inPlaceRequest)); - } - - INLINE const ServiceProviderOptions &ServiceInstanceCreator::getOptions() const { return _options; } - - INLINE containers::ServiceInstanceList *ServiceInstanceCreator::findRegisteredInstances(const TypeId serviceTypeId) - { - const auto singletons = _root.getSingletons().findServices(serviceTypeId); - return singletons ? singletons : _scoped.findServices(serviceTypeId); - } - - INLINE containers::ServiceInstancesMap *ServiceInstanceCreator::tryGetInstancesMap(const ServiceLifeTime &lifeTime) - { - return lifeTime.isTransient() ? nullptr : (lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped); - } - - INLINE const containers::ServiceDescriptorList *ServiceInstanceCreator::findDescriptors( - const TypeId serviceTypeId) const - { - return _root.getDescriptorsMap().findDescriptors(serviceTypeId); - } -} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 27e0cc7..ef593c0 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -5,12 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/Check.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" @@ -23,7 +22,7 @@ namespace sb::di::details::core } INLINE ServiceInstanceProvider::ServiceInstanceProvider(ServiceInstanceProviderRoot &root, - ServiceProviderOptions options) + const ServiceProviderOptions options) : _options(options), _root(root), _scoped(_options.strongDestructionOrder) { } @@ -71,7 +70,7 @@ namespace sb::di::details::core if (!instances->isSealed()) { const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? &createRestInstances(*descriptors, *instances, true) : nullptr; + return descriptors ? &createRestInstances(*descriptors, *instances) : nullptr; } return &instances->getInnerList(); } @@ -89,14 +88,14 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreate(descriptors->last(), false) : nullptr; + return descriptors ? makeInstanceCreator(*descriptors).createInstance() : nullptr; } INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( - TypeId serviceTypeId) + const TypeId serviceTypeId) { const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAll(*descriptors) : std::nullopt; + return descriptors ? makeInstanceCreator(*descriptors).createAllInstances() : std::nullopt; } INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) @@ -115,89 +114,39 @@ namespace sb::di::details::core if (const auto descriptors = findDescriptors(serviceTypeId); descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) { - return tryCreate(descriptors->last(), true); + return makeInstanceCreator(*descriptors).createInstanceInPlace(); } return nullptr; } INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } - INLINE const IServiceInstance *ServiceInstanceProvider::tryCreateAndRegister( + INLINE IServiceInstance *ServiceInstanceProvider::tryCreateAndRegister( const containers::ServiceDescriptorList &descriptors) { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto &instances = - instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); - if (descriptors.size() == 1) - { - instances.seal(); - } - return instances.last().get(); + auto instance = makeInstanceCreator(descriptors).createInstanceInPlace(); + return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); } return nullptr; } - INLINE const OneOrList *ServiceInstanceProvider::tryCreateAndRegisterAll( + INLINE OneOrList *ServiceInstanceProvider::tryCreateAndRegisterAll( const containers::ServiceDescriptorList &descriptors) { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto &instances = - instancesMap->insert(descriptors.getServiceTypeId(), createInstance(descriptors.last(), true)); - return &createRestInstances(descriptors, instances, true); + auto instances = makeInstanceCreator(descriptors).createAllInstancesInPlace(); + return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); } return nullptr; } INLINE OneOrList &ServiceInstanceProvider::createRestInstances( - const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances, - const bool inPlaceRequest) + const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) const { - if (descriptors.size() > 1) - { - instances.reserve(descriptors.size()); - auto realFirst = createInstance(descriptors.first(), inPlaceRequest); - const auto end = --descriptors.end(); - for (auto it = ++descriptors.begin(); it != end; ++it) // skip first and last - { - instances.add(createInstance(*it, inPlaceRequest)); - } - instances.add(std::move(realFirst)); - instances.first().swap(instances.last()); - } - instances.seal(); - return instances.getInnerList(); - } - - INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreate(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) - { - return descriptor.getLifeTime().isTransient() ? createInstance(descriptor, inPlaceRequest) : nullptr; - } - - INLINE std::optional> ServiceInstanceProvider::tryCreateAll( - const containers::ServiceDescriptorList &descriptors) - { - if (descriptors.getLifeTime().isTransient()) - { - containers::ServiceInstanceList instances{createInstance(descriptors.last(), false)}; - createRestInstances(descriptors, instances, false); - return std::move(instances.getInnerList()); - } - return std::nullopt; - } - - INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) - { - if (descriptor.getLifeTime().isSingleton() && this != &_root) - { - return _root.createInstance(descriptor, inPlaceRequest); - } - auto _ = _root.spawnGuard(descriptor.getImplementationTypeId()); - return utils::Require::validInstanceAndGet(descriptor.getImplementationFactory().createInstance( - *utils::Require::notNullAndGet(_serviceProvider), inPlaceRequest)); + return makeInstanceCreator(descriptors).createRestInstancesInPlace(instances).getInnerList(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -218,4 +167,11 @@ namespace sb::di::details::core { return _root.getDescriptorsMap().findDescriptors(serviceTypeId); } + + INLINE ServiceInstancesCreator + ServiceInstanceProvider::makeInstanceCreator(const containers::ServiceDescriptorList &descriptors) const + { + return ServiceInstancesCreator{_root, *_serviceProvider, this == &_root, descriptors}; + } + } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp new file mode 100644 index 0000000..b828e2c --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" + +namespace sb::di::details::core +{ + INLINE ServiceInstancesCreator::ServiceInstancesCreator(ServiceInstanceProviderRoot &root, + ServiceProvider &provider, const bool isThisRoot, + const containers::ServiceDescriptorList &descriptors) + : _root(root), _serviceProvider(provider), _descriptors(descriptors), _isThisRoot(isThisRoot) + { + } + + INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance() { return createInstance(false); } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstance() + { + return createOneInstance(false); + } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstances() + { + return createAllInstances(false); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstances( + containers::ServiceInstanceList &instances) + { + return createRestInstances(instances, false); + } + + INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstanceInPlace() { return createInstance(true); } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstanceInPlace() + { + return createOneInstance(true); + } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstancesInPlace() + { + return createAllInstances(true); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstancesInPlace( + containers::ServiceInstanceList &instances) + { + return createRestInstances(instances, true); + } + + INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const bool inPlaceRequest) + { + return createInstance(_descriptors.last(), inPlaceRequest); + } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstance(const bool inPlaceRequest) + { + containers::ServiceInstanceList instances{createInstance(_descriptors.last(), inPlaceRequest)}; + if (_descriptors.size() == 1) + { + instances.seal(); + } + return instances; + } + + INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstances(const bool inPlaceRequest) + { + containers::ServiceInstanceList instances{createInstance(_descriptors.last(), inPlaceRequest)}; + return std::move(createRestInstances(instances, true)); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstances( + containers::ServiceInstanceList &instances, const bool inPlaceRequest) + { + if (_descriptors.size() > 1) + { + instances.reserve(_descriptors.size()); + auto realFirst = createInstance(_descriptors.first(), inPlaceRequest); + const auto end = --_descriptors.end(); + for (auto it = ++_descriptors.begin(); it != end; ++it) // skip first and last + { + instances.add(createInstance(*it, inPlaceRequest)); + } + instances.add(std::move(realFirst)); + instances.first().swap(instances.last()); + } + instances.seal(); + return instances; + } + + INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) + { + if (descriptor.getLifeTime().isSingleton() && !_isThisRoot) + { + return _root.createInstance(descriptor, inPlaceRequest); + } + auto _ = _root.spawnGuard(descriptor.getImplementationTypeId()); + return utils::Require::validInstanceAndGet( + descriptor.getImplementationFactory().createInstance(_serviceProvider, inPlaceRequest)); + } +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp deleted file mode 100644 index b2e0dbb..0000000 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" -#include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/TypeId.hpp" - -namespace sb::di::details::core -{ - class EXPORT ServiceInstanceCreator - { - ServiceProvider &_provider; - containers::ServiceDescriptorList &_descriptors; - - public: - using Ptr = std::unique_ptr; - - explicit ServiceInstanceCreator(ServiceProvider &provider, containers::ServiceDescriptorList &descriptors); - - const IServiceInstance *tryCreateAndRegister(); - - const OneOrList *tryCreateAndRegisterAll( - const containers::ServiceDescriptorList &descriptors); - - IServiceInstance::Ptr tryCreate(const ServiceDescriptor &descriptor, bool inPlaceRequest); - std::optional> tryCreateAll( - const containers::ServiceDescriptorList &descriptors); - - OneOrList &createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances, - bool inPlaceRequest); - - IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); - - containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); - }; -} // namespace sb::di::details::core - -#ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp" -#endif diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index c1d499f..8719759 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -1,5 +1,6 @@ #pragma once + #include #include @@ -7,6 +8,7 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" @@ -55,25 +57,20 @@ namespace sb::di::details::core [[nodiscard]] const ServiceProviderOptions &getOptions() const override; protected: - const IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - const OneOrList *tryCreateAndRegisterAll( - const containers::ServiceDescriptorList &descriptors); + IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - IServiceInstance::Ptr tryCreate(const ServiceDescriptor &descriptor, bool inPlaceRequest); - std::optional> tryCreateAll( - const containers::ServiceDescriptorList &descriptors); + OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); OneOrList &createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances, - bool inPlaceRequest); - - IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + containers::ServiceInstanceList &instances) const; containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; + + [[nodiscard]] ServiceInstancesCreator makeInstanceCreator(const containers::ServiceDescriptorList &descriptors) const; }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp new file mode 100644 index 0000000..ca43266 --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" +#include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceDescriptor.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di::details::core +{ + class ServiceInstanceProviderRoot; + + class EXPORT ServiceInstancesCreator + { + ServiceInstanceProviderRoot &_root; + ServiceProvider &_serviceProvider; + const containers::ServiceDescriptorList &_descriptors; + bool _isThisRoot; + + public: + explicit ServiceInstancesCreator(ServiceInstanceProviderRoot &root, ServiceProvider &provider, bool isThisRoot, + const containers::ServiceDescriptorList &descriptors); + + IServiceInstance::Ptr createInstance(); + + containers::ServiceInstanceList createOneInstance(); + + containers::ServiceInstanceList createAllInstances(); + + containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances); + + IServiceInstance::Ptr createInstanceInPlace(); + + containers::ServiceInstanceList createOneInstanceInPlace(); + + containers::ServiceInstanceList createAllInstancesInPlace(); + + containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances); + + private: + IServiceInstance::Ptr createInstance(bool inPlaceRequest); + + containers::ServiceInstanceList createOneInstance(bool inPlaceRequest); + + containers::ServiceInstanceList createAllInstances(bool inPlaceRequest); + + containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, + bool inPlaceRequest); + + IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + }; +} // namespace sb::di::details::core + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp" +#endif From 9f6981b253ed94fcccb8f78f2b5d93c7b3200eb5 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 24 Jan 2024 17:42:35 +0100 Subject: [PATCH 09/45] refactor provider code --- .../Core/Impl/ServiceInstanceProvider.hpp | 34 ++++++++++------ .../Core/Impl/ServiceInstanceProviderRoot.hpp | 2 - .../Core/Impl/ServiceInstancesCreator.hpp | 39 ++++++++----------- .../Core/Impl/ServiceInstancesCreatorCtx.hpp | 28 +++++++++++++ .../Details/Core/ServiceInstanceProvider.hpp | 15 +++---- .../Core/ServiceInstanceProviderRoot.hpp | 2 +- .../Details/Core/ServiceInstancesCreator.hpp | 17 +++----- .../Core/ServiceInstancesCreatorCtx.hpp | 30 ++++++++++++++ 8 files changed, 111 insertions(+), 56 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp create mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index ef593c0..931cd54 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -87,15 +87,22 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? makeInstanceCreator(*descriptors).createInstance() : nullptr; + if (const auto descriptors = findDescriptors(serviceTypeId)) + { + return ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createInstance(); + } + return nullptr; } INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? makeInstanceCreator(*descriptors).createAllInstances() : std::nullopt; + if (const auto descriptors = findDescriptors(serviceTypeId)) + { + auto instances = ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createAllInstances(); + return std::move(instances.getInnerList()); + } + return std::nullopt; } INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) @@ -114,7 +121,7 @@ namespace sb::di::details::core if (const auto descriptors = findDescriptors(serviceTypeId); descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) { - return makeInstanceCreator(*descriptors).createInstanceInPlace(); + return ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createInstanceInPlace(); } return nullptr; } @@ -126,7 +133,7 @@ namespace sb::di::details::core { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto instance = makeInstanceCreator(descriptors).createInstanceInPlace(); + auto instance = ServiceInstancesCreator{makeCreatorCtx(descriptors)}.createInstanceInPlace(); return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); } return nullptr; @@ -137,16 +144,18 @@ namespace sb::di::details::core { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto instances = makeInstanceCreator(descriptors).createAllInstancesInPlace(); + auto instances = ServiceInstancesCreator{makeCreatorCtx(descriptors)}.createAllInstancesInPlace(); return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); } return nullptr; } INLINE OneOrList &ServiceInstanceProvider::createRestInstances( - const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) const + const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - return makeInstanceCreator(descriptors).createRestInstancesInPlace(instances).getInnerList(); + return ServiceInstancesCreator{makeCreatorCtx(descriptors)} + .createRestInstancesInPlace(instances) + .getInnerList(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -168,10 +177,11 @@ namespace sb::di::details::core return _root.getDescriptorsMap().findDescriptors(serviceTypeId); } - INLINE ServiceInstancesCreator - ServiceInstanceProvider::makeInstanceCreator(const containers::ServiceDescriptorList &descriptors) const + INLINE ServiceInstancesCreatorCtx + ServiceInstanceProvider::makeCreatorCtx(const containers::ServiceDescriptorList &descriptors) { - return ServiceInstancesCreator{_root, *_serviceProvider, this == &_root, descriptors}; + return ServiceInstancesCreatorCtx{ + descriptors.getLifeTime().isSingleton() ? _root._serviceProvider : _serviceProvider, _guard, descriptors}; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index b62f0ce..1110c64 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -22,8 +22,6 @@ namespace sb::di::details::core INLINE containers::ServiceInstancesMap &ServiceInstanceProviderRoot::getSingletons() { return _singletons; } - INLINE helpers::ScopedGuard ServiceInstanceProviderRoot::spawnGuard(const TypeId typeId) { return _guard(typeId); } - INLINE void ServiceInstanceProviderRoot::prebuildSingletons() { for (auto &[_, descriptors] : getDescriptorsMap()) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp index b828e2c..56c2ca8 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp @@ -5,17 +5,13 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" namespace sb::di::details::core { - INLINE ServiceInstancesCreator::ServiceInstancesCreator(ServiceInstanceProviderRoot &root, - ServiceProvider &provider, const bool isThisRoot, - const containers::ServiceDescriptorList &descriptors) - : _root(root), _serviceProvider(provider), _descriptors(descriptors), _isThisRoot(isThisRoot) - { - } + INLINE ServiceInstancesCreator::ServiceInstancesCreator(const ServiceInstancesCreatorCtx &ctx) : _ctx(ctx) {} INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance() { return createInstance(false); } @@ -55,13 +51,14 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const bool inPlaceRequest) { - return createInstance(_descriptors.last(), inPlaceRequest); + return createInstance(_ctx.getDescriptors().last(), inPlaceRequest); } INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstance(const bool inPlaceRequest) { - containers::ServiceInstanceList instances{createInstance(_descriptors.last(), inPlaceRequest)}; - if (_descriptors.size() == 1) + auto &desctiptors = _ctx.getDescriptors(); + containers::ServiceInstanceList instances{createInstance(desctiptors.last(), inPlaceRequest)}; + if (desctiptors.size() == 1) { instances.seal(); } @@ -70,19 +67,19 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstances(const bool inPlaceRequest) { - containers::ServiceInstanceList instances{createInstance(_descriptors.last(), inPlaceRequest)}; + containers::ServiceInstanceList instances{createInstance(_ctx.getDescriptors().last(), inPlaceRequest)}; return std::move(createRestInstances(instances, true)); } INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstances( containers::ServiceInstanceList &instances, const bool inPlaceRequest) { - if (_descriptors.size() > 1) + if (auto &desctiptors = _ctx.getDescriptors(); desctiptors.size() > 1) { - instances.reserve(_descriptors.size()); - auto realFirst = createInstance(_descriptors.first(), inPlaceRequest); - const auto end = --_descriptors.end(); - for (auto it = ++_descriptors.begin(); it != end; ++it) // skip first and last + instances.reserve(desctiptors.size()); + auto realFirst = createInstance(desctiptors.first(), inPlaceRequest); + const auto end = --desctiptors.end(); + for (auto it = ++desctiptors.begin(); it != end; ++it) // skip first and last { instances.add(createInstance(*it, inPlaceRequest)); } @@ -94,14 +91,10 @@ namespace sb::di::details::core } INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) + const bool inPlaceRequest) { - if (descriptor.getLifeTime().isSingleton() && !_isThisRoot) - { - return _root.createInstance(descriptor, inPlaceRequest); - } - auto _ = _root.spawnGuard(descriptor.getImplementationTypeId()); + auto _ = _ctx.getGuard().spawnGuard(descriptor.getImplementationTypeId()); return utils::Require::validInstanceAndGet( - descriptor.getImplementationFactory().createInstance(_serviceProvider, inPlaceRequest)); + descriptor.getImplementationFactory().createInstance(_ctx.getServiceProvider(), inPlaceRequest)); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp new file mode 100644 index 0000000..8ad042c --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" + +namespace sb::di::details::core +{ + INLINE ServiceInstancesCreatorCtx::ServiceInstancesCreatorCtx(ServiceProvider *serviceProvider, + helpers::CircularDependencyGuard &guard, + const containers::ServiceDescriptorList &descriptors) + : _serviceProvider(serviceProvider), _guard(guard), _descriptors(descriptors) + { + } + + INLINE ServiceProvider &ServiceInstancesCreatorCtx::getServiceProvider() const + { + return *utils::Require::notNullAndGet(_serviceProvider); + } + + INLINE helpers::CircularDependencyGuard &ServiceInstancesCreatorCtx::getGuard() const { return _guard; } + + INLINE const containers::ServiceDescriptorList &ServiceInstancesCreatorCtx::getDescriptors() const + { + return _descriptors; + } +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 8719759..9003f16 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -1,6 +1,5 @@ #pragma once - #include #include @@ -8,11 +7,10 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" +#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" #include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::core @@ -22,10 +20,13 @@ namespace sb::di::details::core class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; - ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; + + ServiceInstanceProviderRoot &_root; ServiceProvider *_serviceProvider = nullptr; + helpers::CircularDependencyGuard _guard; + ServiceInstanceProvider(const ServiceInstanceProvider &provider); public: @@ -62,7 +63,7 @@ namespace sb::di::details::core OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); OneOrList &createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances) const; + containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); @@ -70,7 +71,7 @@ namespace sb::di::details::core [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; - [[nodiscard]] ServiceInstancesCreator makeInstanceCreator(const containers::ServiceDescriptorList &descriptors) const; + ServiceInstancesCreatorCtx makeCreatorCtx(const containers::ServiceDescriptorList &descriptors); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index 2015521..2f14923 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -7,6 +7,7 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" @@ -16,7 +17,6 @@ namespace sb::di::details::core { containers::ServiceDescriptorsMap _descriptorsMap; containers::ServiceInstancesMap _singletons; - helpers::CircularDependencyGuard _guard; public: using Ptr = std::unique_ptr; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp index ca43266..76f4d50 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp @@ -4,25 +4,20 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" +#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::core { - class ServiceInstanceProviderRoot; - class EXPORT ServiceInstancesCreator { - ServiceInstanceProviderRoot &_root; - ServiceProvider &_serviceProvider; - const containers::ServiceDescriptorList &_descriptors; - bool _isThisRoot; + ServiceInstancesCreatorCtx _ctx; public: - explicit ServiceInstancesCreator(ServiceInstanceProviderRoot &root, ServiceProvider &provider, bool isThisRoot, - const containers::ServiceDescriptorList &descriptors); + explicit ServiceInstancesCreator(const ServiceInstancesCreatorCtx &ctx); + + ServiceInstancesCreator(ServiceInstancesCreator &&) = default; IServiceInstance::Ptr createInstance(); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp new file mode 100644 index 0000000..71b2480 --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" +#include "SevenBit/DI/ServiceDescriptor.hpp" + +namespace sb::di::details::core +{ + class EXPORT ServiceInstancesCreatorCtx + { + ServiceProvider *_serviceProvider = nullptr; + helpers::CircularDependencyGuard &_guard; + const containers::ServiceDescriptorList &_descriptors; + + public: + ServiceInstancesCreatorCtx(ServiceProvider *serviceProvider, helpers::CircularDependencyGuard &guard, + const containers::ServiceDescriptorList &descriptors); + + [[nodiscard]] ServiceProvider &getServiceProvider() const; + + [[nodiscard]] helpers::CircularDependencyGuard &getGuard() const; + + [[nodiscard]] const containers::ServiceDescriptorList &getDescriptors() const; + }; +} // namespace sb::di::details::core + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp" +#endif From 1b36ed00ac6de70f694a5d4c19365f4459154e06 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 24 Jan 2024 19:14:35 +0100 Subject: [PATCH 10/45] code refactor --- .../Containers/Impl/ServiceDescriptorsMap.hpp | 2 +- .../Containers/Impl/ServiceInstancesMap.hpp | 2 +- .../Core/Impl/ServiceInstanceCreator.hpp | 25 +++++ .../Core/Impl/ServiceInstanceProvider.hpp | 28 +++-- .../Core/Impl/ServiceInstancesCreator.hpp | 100 ------------------ .../Core/Impl/ServiceInstancesCreatorCtx.hpp | 28 ----- .../Core/Impl/ServiceInstancesResolver.hpp | 93 ++++++++++++++++ .../Details/Core/ServiceInstanceCreator.hpp | 24 +++++ .../Details/Core/ServiceInstanceProvider.hpp | 13 +-- .../Core/ServiceInstancesCreatorCtx.hpp | 30 ------ ...eator.hpp => ServiceInstancesResolver.hpp} | 17 ++- .../DI/Details/Helpers/Impl/ScopedGuard.hpp | 3 +- Include/SevenBit/DI/IServiceInstance.hpp | 1 - 13 files changed, 168 insertions(+), 198 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp delete mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp delete mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp create mode 100644 Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp create mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp delete mode 100644 Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp rename Include/SevenBit/DI/Details/Core/{ServiceInstancesCreator.hpp => ServiceInstancesResolver.hpp} (69%) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp index 38fe7ff..651e512 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp @@ -52,7 +52,7 @@ namespace sb::di::details::containers INLINE void ServiceDescriptorsMap::checkIfAlreadyRegistered(const TypeId implementationTypeId) { - if (const auto it = _registeredServices.find(implementationTypeId); it != _registeredServices.end()) + if (_registeredServices.count(implementationTypeId)) { throw ServiceAlreadyRegisteredException{implementationTypeId}; } diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index 71ca418..1547355 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -28,7 +28,7 @@ namespace sb::di::details::containers INLINE bool ServiceInstancesMap::contains(const TypeId serviceTypeId) const { - return _serviceListMap.find(serviceTypeId) != _serviceListMap.end(); + return _serviceListMap.count(serviceTypeId); } INLINE ServiceInstanceList *ServiceInstancesMap::findServices(const TypeId serviceTypeId) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp new file mode 100644 index 0000000..8f0c11f --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" + +namespace sb::di::details::core +{ + INLINE void ServiceInstanceCreator::setServiceProvider(ServiceProvider *serviceProvider) + { + _serviceProvider = serviceProvider; + } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) + { + auto &provider = *utils::Require::notNullAndGet(_serviceProvider); + auto &factory = descriptor.getImplementationFactory(); + auto _ = _guard.spawnGuard(descriptor.getImplementationTypeId()); + return utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); + } +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 931cd54..187064d 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" @@ -29,8 +28,8 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::init(ServiceProvider &serviceProvider) { - _serviceProvider = &serviceProvider; - auto external = std::make_unique>(_serviceProvider); + _instanceCreator.setServiceProvider(&serviceProvider); + auto external = std::make_unique>(&serviceProvider); _scoped.insert(typeid(ServiceProvider), std::move(external)).seal(); } @@ -89,7 +88,7 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - return ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createInstance(); + return makeResolver(*descriptors).createInstance(); } return nullptr; } @@ -99,7 +98,7 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - auto instances = ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createAllInstances(); + auto instances = makeResolver(*descriptors).createAllInstances(); return std::move(instances.getInnerList()); } return std::nullopt; @@ -121,7 +120,7 @@ namespace sb::di::details::core if (const auto descriptors = findDescriptors(serviceTypeId); descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) { - return ServiceInstancesCreator{makeCreatorCtx(*descriptors)}.createInstanceInPlace(); + return makeResolver(*descriptors).createInstanceInPlace(); } return nullptr; } @@ -133,7 +132,7 @@ namespace sb::di::details::core { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto instance = ServiceInstancesCreator{makeCreatorCtx(descriptors)}.createInstanceInPlace(); + auto instance = makeResolver(descriptors).createInstanceInPlace(); return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); } return nullptr; @@ -144,7 +143,7 @@ namespace sb::di::details::core { if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) { - auto instances = ServiceInstancesCreator{makeCreatorCtx(descriptors)}.createAllInstancesInPlace(); + auto instances = makeResolver(descriptors).createAllInstancesInPlace(); return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); } return nullptr; @@ -153,9 +152,7 @@ namespace sb::di::details::core INLINE OneOrList &ServiceInstanceProvider::createRestInstances( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - return ServiceInstancesCreator{makeCreatorCtx(descriptors)} - .createRestInstancesInPlace(instances) - .getInnerList(); + return makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -177,11 +174,10 @@ namespace sb::di::details::core return _root.getDescriptorsMap().findDescriptors(serviceTypeId); } - INLINE ServiceInstancesCreatorCtx - ServiceInstanceProvider::makeCreatorCtx(const containers::ServiceDescriptorList &descriptors) + INLINE ServiceInstancesResolver + ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { - return ServiceInstancesCreatorCtx{ - descriptors.getLifeTime().isSingleton() ? _root._serviceProvider : _serviceProvider, _guard, descriptors}; + auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; + return ServiceInstancesResolver{creator, descriptors}; } - } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp deleted file mode 100644 index 56c2ca8..0000000 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" - -namespace sb::di::details::core -{ - INLINE ServiceInstancesCreator::ServiceInstancesCreator(const ServiceInstancesCreatorCtx &ctx) : _ctx(ctx) {} - - INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance() { return createInstance(false); } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstance() - { - return createOneInstance(false); - } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstances() - { - return createAllInstances(false); - } - - INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstances( - containers::ServiceInstanceList &instances) - { - return createRestInstances(instances, false); - } - - INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstanceInPlace() { return createInstance(true); } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstanceInPlace() - { - return createOneInstance(true); - } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstancesInPlace() - { - return createAllInstances(true); - } - - INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstancesInPlace( - containers::ServiceInstanceList &instances) - { - return createRestInstances(instances, true); - } - - INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const bool inPlaceRequest) - { - return createInstance(_ctx.getDescriptors().last(), inPlaceRequest); - } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createOneInstance(const bool inPlaceRequest) - { - auto &desctiptors = _ctx.getDescriptors(); - containers::ServiceInstanceList instances{createInstance(desctiptors.last(), inPlaceRequest)}; - if (desctiptors.size() == 1) - { - instances.seal(); - } - return instances; - } - - INLINE containers::ServiceInstanceList ServiceInstancesCreator::createAllInstances(const bool inPlaceRequest) - { - containers::ServiceInstanceList instances{createInstance(_ctx.getDescriptors().last(), inPlaceRequest)}; - return std::move(createRestInstances(instances, true)); - } - - INLINE containers::ServiceInstanceList &ServiceInstancesCreator::createRestInstances( - containers::ServiceInstanceList &instances, const bool inPlaceRequest) - { - if (auto &desctiptors = _ctx.getDescriptors(); desctiptors.size() > 1) - { - instances.reserve(desctiptors.size()); - auto realFirst = createInstance(desctiptors.first(), inPlaceRequest); - const auto end = --desctiptors.end(); - for (auto it = ++desctiptors.begin(); it != end; ++it) // skip first and last - { - instances.add(createInstance(*it, inPlaceRequest)); - } - instances.add(std::move(realFirst)); - instances.first().swap(instances.last()); - } - instances.seal(); - return instances; - } - - INLINE IServiceInstance::Ptr ServiceInstancesCreator::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) - { - auto _ = _ctx.getGuard().spawnGuard(descriptor.getImplementationTypeId()); - return utils::Require::validInstanceAndGet( - descriptor.getImplementationFactory().createInstance(_ctx.getServiceProvider(), inPlaceRequest)); - } -} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp deleted file mode 100644 index 8ad042c..0000000 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" - -namespace sb::di::details::core -{ - INLINE ServiceInstancesCreatorCtx::ServiceInstancesCreatorCtx(ServiceProvider *serviceProvider, - helpers::CircularDependencyGuard &guard, - const containers::ServiceDescriptorList &descriptors) - : _serviceProvider(serviceProvider), _guard(guard), _descriptors(descriptors) - { - } - - INLINE ServiceProvider &ServiceInstancesCreatorCtx::getServiceProvider() const - { - return *utils::Require::notNullAndGet(_serviceProvider); - } - - INLINE helpers::CircularDependencyGuard &ServiceInstancesCreatorCtx::getGuard() const { return _guard; } - - INLINE const containers::ServiceDescriptorList &ServiceInstancesCreatorCtx::getDescriptors() const - { - return _descriptors; - } -} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp new file mode 100644 index 0000000..0725280 --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" + +namespace sb::di::details::core +{ + INLINE ServiceInstancesResolver::ServiceInstancesResolver(ServiceInstanceCreator &creator, + const containers::ServiceDescriptorList &descriptors) + : _creator(creator), _descriptors(descriptors) + { + } + + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance() { return createInstance(false); } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance() + { + return createOneInstance(false); + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances() + { + return createAllInstances(false); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( + containers::ServiceInstanceList &instances) + { + return createRestInstances(instances, false); + } + + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() { return createInstance(true); } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstanceInPlace() + { + return createOneInstance(true); + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstancesInPlace() + { + return createAllInstances(true); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstancesInPlace( + containers::ServiceInstanceList &instances) + { + return createRestInstances(instances, true); + } + + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) + { + return _creator.createInstance(_descriptors.last(), inPlaceRequest); + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance(const bool inPlaceRequest) + { + containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; + if (_descriptors.size() == 1) + { + instances.seal(); + } + return instances; + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances(const bool inPlaceRequest) + { + containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; + return std::move(createRestInstances(instances, true)); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( + containers::ServiceInstanceList &instances, const bool inPlaceRequest) + { + if (_descriptors.size() > 1) + { + instances.reserve(_descriptors.size()); + auto realFirst = _creator.createInstance(_descriptors.first(), inPlaceRequest); + const auto end = --_descriptors.end(); + for (auto it = ++_descriptors.begin(); it != end; ++it) // skip first and last + { + instances.add(_creator.createInstance(*it, inPlaceRequest)); + } + instances.add(std::move(realFirst)); + instances.first().swap(instances.last()); + } + instances.seal(); + return instances; + } +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp new file mode 100644 index 0000000..2f36a54 --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" +#include "SevenBit/DI/ServiceDescriptor.hpp" + +namespace sb::di::details::core +{ + class EXPORT ServiceInstanceCreator + { + ServiceProvider *_serviceProvider = nullptr; + helpers::CircularDependencyGuard _guard; + + public: + void setServiceProvider(ServiceProvider *serviceProvider); + + IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + }; +} // namespace sb::di::details::core + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp" +#endif diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 9003f16..62beeba 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -7,8 +7,8 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" -#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" #include "SevenBit/DI/TypeId.hpp" @@ -20,12 +20,9 @@ namespace sb::di::details::core class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; - containers::ServiceInstancesMap _scoped; - + ServiceInstanceCreator _instanceCreator; ServiceInstanceProviderRoot &_root; - ServiceProvider *_serviceProvider = nullptr; - - helpers::CircularDependencyGuard _guard; + containers::ServiceInstancesMap _scoped; ServiceInstanceProvider(const ServiceInstanceProvider &provider); @@ -71,7 +68,7 @@ namespace sb::di::details::core [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; - ServiceInstancesCreatorCtx makeCreatorCtx(const containers::ServiceDescriptorList &descriptors); + ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp deleted file mode 100644 index 71b2480..0000000 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" - -namespace sb::di::details::core -{ - class EXPORT ServiceInstancesCreatorCtx - { - ServiceProvider *_serviceProvider = nullptr; - helpers::CircularDependencyGuard &_guard; - const containers::ServiceDescriptorList &_descriptors; - - public: - ServiceInstancesCreatorCtx(ServiceProvider *serviceProvider, helpers::CircularDependencyGuard &guard, - const containers::ServiceDescriptorList &descriptors); - - [[nodiscard]] ServiceProvider &getServiceProvider() const; - - [[nodiscard]] helpers::CircularDependencyGuard &getGuard() const; - - [[nodiscard]] const containers::ServiceDescriptorList &getDescriptors() const; - }; -} // namespace sb::di::details::core - -#ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesCreatorCtx.hpp" -#endif diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp similarity index 69% rename from Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp rename to Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index 76f4d50..c3687b9 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -4,20 +4,17 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstancesCreatorCtx.hpp" -#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" namespace sb::di::details::core { - class EXPORT ServiceInstancesCreator + class EXPORT ServiceInstancesResolver { - ServiceInstancesCreatorCtx _ctx; + ServiceInstanceCreator &_creator; + const containers::ServiceDescriptorList &_descriptors; public: - explicit ServiceInstancesCreator(const ServiceInstancesCreatorCtx &ctx); - - ServiceInstancesCreator(ServiceInstancesCreator &&) = default; + ServiceInstancesResolver(ServiceInstanceCreator &creator, const containers::ServiceDescriptorList &descriptors); IServiceInstance::Ptr createInstance(); @@ -44,11 +41,9 @@ namespace sb::di::details::core containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, bool inPlaceRequest); - - IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); }; } // namespace sb::di::details::core #ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesCreator.hpp" +#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp" #endif diff --git a/Include/SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp b/Include/SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp index 18f9d2c..2308919 100644 --- a/Include/SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp +++ b/Include/SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp @@ -13,8 +13,7 @@ namespace sb::di::details::helpers std::unordered_set &typeIdsUnderConstruction) : _typeIdsUnderConstruction(typeIdsUnderConstruction), _typeIdUnderConstruction(typeIdUnderConstruction) { - if (const auto it = _typeIdsUnderConstruction.find(_typeIdUnderConstruction); - it != _typeIdsUnderConstruction.end()) + if (_typeIdsUnderConstruction.count(_typeIdUnderConstruction)) { throw CircularDependencyException{_typeIdUnderConstruction}; } diff --git a/Include/SevenBit/DI/IServiceInstance.hpp b/Include/SevenBit/DI/IServiceInstance.hpp index f23734e..8e8a30e 100644 --- a/Include/SevenBit/DI/IServiceInstance.hpp +++ b/Include/SevenBit/DI/IServiceInstance.hpp @@ -4,7 +4,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di From 7cc5a14cb19d5bbaa004071526d2ec66566b6d7f Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 24 Jan 2024 23:10:45 +0100 Subject: [PATCH 11/45] code refactor --- .../DI/Details/Core/Impl/ServiceInstanceCreator.hpp | 6 +++--- .../DI/Details/Core/Impl/ServiceInstanceProvider.hpp | 12 ++++++++---- .../Details/Core/Impl/ServiceInstancesResolver.hpp | 4 ++-- .../DI/Details/Core/ServiceInstanceCreator.hpp | 2 +- .../DI/Details/Core/ServiceInstanceProvider.hpp | 4 ++-- Include/SevenBit/DI/Impl/ServiceDescriptor.hpp | 5 ++--- Source/Source.cpp | 1 + Tests/Integration/ComplexInjectionsTest.cpp | 4 ++-- 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 8f0c11f..26c9d2b 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -9,9 +9,9 @@ namespace sb::di::details::core { - INLINE void ServiceInstanceCreator::setServiceProvider(ServiceProvider *serviceProvider) + INLINE void ServiceInstanceCreator::setServiceProvider(ServiceProvider &serviceProvider) { - _serviceProvider = serviceProvider; + _serviceProvider = &serviceProvider; } INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, @@ -19,7 +19,7 @@ namespace sb::di::details::core { auto &provider = *utils::Require::notNullAndGet(_serviceProvider); auto &factory = descriptor.getImplementationFactory(); - auto _ = _guard.spawnGuard(descriptor.getImplementationTypeId()); + auto _ = _guard(descriptor.getImplementationTypeId()); return utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 187064d..198a692 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -12,6 +12,7 @@ #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" namespace sb::di::details::core { @@ -28,7 +29,7 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::init(ServiceProvider &serviceProvider) { - _instanceCreator.setServiceProvider(&serviceProvider); + _instanceCreator.setServiceProvider(serviceProvider); auto external = std::make_unique>(&serviceProvider); _scoped.insert(typeid(ServiceProvider), std::move(external)).seal(); } @@ -86,7 +87,8 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId)) + if (const auto descriptors = findDescriptors(serviceTypeId); + descriptors && descriptors->getLifeTime().isTransient()) { return makeResolver(*descriptors).createInstance(); } @@ -96,7 +98,8 @@ namespace sb::di::details::core INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId)) + if (const auto descriptors = findDescriptors(serviceTypeId); + descriptors && descriptors->getLifeTime().isTransient()) { auto instances = makeResolver(*descriptors).createAllInstances(); return std::move(instances.getInnerList()); @@ -118,7 +121,8 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId); - descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) + descriptors && descriptors->getLifeTime().isTransient() && + descriptors->last().getImplementationTypeId() == serviceTypeId) { return makeResolver(*descriptors).createInstanceInPlace(); } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 0725280..279890e 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -10,7 +10,7 @@ namespace sb::di::details::core { INLINE ServiceInstancesResolver::ServiceInstancesResolver(ServiceInstanceCreator &creator, - const containers::ServiceDescriptorList &descriptors) + const containers::ServiceDescriptorList &descriptors) : _creator(creator), _descriptors(descriptors) { } @@ -69,7 +69,7 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances(const bool inPlaceRequest) { containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; - return std::move(createRestInstances(instances, true)); + return std::move(createRestInstances(instances, inPlaceRequest)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index 2f36a54..5726671 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -13,7 +13,7 @@ namespace sb::di::details::core helpers::CircularDependencyGuard _guard; public: - void setServiceProvider(ServiceProvider *serviceProvider); + void setServiceProvider(ServiceProvider &serviceProvider); IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); }; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 62beeba..707680e 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -9,7 +9,7 @@ #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstanceProvider.hpp" #include "SevenBit/DI/ServiceLifeTime.hpp" #include "SevenBit/DI/TypeId.hpp" @@ -20,8 +20,8 @@ namespace sb::di::details::core class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; - ServiceInstanceCreator _instanceCreator; ServiceInstanceProviderRoot &_root; + ServiceInstanceCreator _instanceCreator; containers::ServiceInstancesMap _scoped; ServiceInstanceProvider(const ServiceInstanceProvider &provider); diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index d0a5e5d..48108ce 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -10,10 +10,9 @@ namespace sb::di { INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const ServiceLifeTime lifetime, IServiceFactory::Ptr implementationFactory) - : _serviceTypeId(serviceTypeId), _lifetime(lifetime), - _implementationFactory(details::utils::Require::notNullAndGet(std::move(implementationFactory), - "Implementation factory cannot be null")) + : _serviceTypeId(serviceTypeId), _lifetime(lifetime), _implementationFactory(std::move(implementationFactory)) { + details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); } INLINE const ServiceLifeTime &ServiceDescriptor::getLifeTime() const { return _lifetime; } diff --git a/Source/Source.cpp b/Source/Source.cpp index 79da9a3..8253f23 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -8,6 +8,7 @@ #include "SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp" +#include "SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp" #include "SevenBit/DI/Details/Helpers/Impl/CircularDependencyGuard.hpp" #include "SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp" #include "SevenBit/DI/Details/Utils/Impl/Check.hpp" diff --git a/Tests/Integration/ComplexInjectionsTest.cpp b/Tests/Integration/ComplexInjectionsTest.cpp index 366db06..c67d2c8 100644 --- a/Tests/Integration/ComplexInjectionsTest.cpp +++ b/Tests/Integration/ComplexInjectionsTest.cpp @@ -65,10 +65,10 @@ TEST_F(ComplexInjectionsTest, ShouldTryGetDeepNestedService) { sb::di::ServiceCollection collection; - TestNested<50>::addAllRecurse(collection); + TestNested<60>::addAllRecurse(collection); auto provider = collection.buildServiceProvider(); - auto nested = provider.getService>(); + auto nested = provider.getService>(); nested.checkRecurse(provider); } From ce35823e44239bf36cd11e20e39f0049a570e614 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Thu, 25 Jan 2024 19:11:21 +0100 Subject: [PATCH 12/45] refactor provider code --- .../Core/Impl/ServiceInstanceProvider.hpp | 16 ++++++----- .../Core/Impl/ServiceInstancesResolver.hpp | 27 ++++++++++--------- .../Details/Core/ServiceInstanceProvider.hpp | 4 +-- .../Core/ServiceInstanceProviderRoot.hpp | 2 -- .../Details/Core/ServiceInstancesResolver.hpp | 24 ++++++++--------- .../SevenBit/DI/IServiceInstanceProvider.hpp | 12 ++++----- Include/SevenBit/DI/ServiceProvider.hpp | 13 +++------ 7 files changed, 47 insertions(+), 51 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 198a692..01f9999 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -11,8 +11,8 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProviderOptions.hpp" #include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core { @@ -31,7 +31,7 @@ namespace sb::di::details::core { _instanceCreator.setServiceProvider(serviceProvider); auto external = std::make_unique>(&serviceProvider); - _scoped.insert(typeid(ServiceProvider), std::move(external)).seal(); + _scoped.insert(external->getTypeId(), std::move(external)).seal(); } INLINE IServiceInstanceProvider::Ptr ServiceInstanceProvider::createScope() const @@ -70,7 +70,7 @@ namespace sb::di::details::core if (!instances->isSealed()) { const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? &createRestInstances(*descriptors, *instances) : nullptr; + return descriptors ? createRestInstances(*descriptors, *instances) : nullptr; } return &instances->getInnerList(); } @@ -153,10 +153,10 @@ namespace sb::di::details::core return nullptr; } - INLINE OneOrList &ServiceInstanceProvider::createRestInstances( + INLINE OneOrList *ServiceInstanceProvider::createRestInstances( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - return makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); + return &makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -169,7 +169,11 @@ namespace sb::di::details::core INLINE containers::ServiceInstancesMap *ServiceInstanceProvider::tryGetInstancesMap(const ServiceLifeTime &lifeTime) { - return lifeTime.isTransient() ? nullptr : (lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped); + if (lifeTime.isTransient()) + { + return nullptr; + } + return lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped; } INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors( diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 279890e..7c6c93f 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -15,48 +15,51 @@ namespace sb::di::details::core { } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance() { return createInstance(false); } + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance() const { return createInstance(false); } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance() + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance() const { return createOneInstance(false); } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances() + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances() const { return createAllInstances(false); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( - containers::ServiceInstanceList &instances) + containers::ServiceInstanceList &instances) const { return createRestInstances(instances, false); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() { return createInstance(true); } + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() const + { + return createInstance(true); + } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstanceInPlace() + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstanceInPlace() const { return createOneInstance(true); } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstancesInPlace() + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstancesInPlace() const { return createAllInstances(true); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstancesInPlace( - containers::ServiceInstanceList &instances) + containers::ServiceInstanceList &instances) const { return createRestInstances(instances, true); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const { return _creator.createInstance(_descriptors.last(), inPlaceRequest); } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance(const bool inPlaceRequest) + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance(const bool inPlaceRequest) const { containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; if (_descriptors.size() == 1) @@ -66,14 +69,14 @@ namespace sb::di::details::core return instances; } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances(const bool inPlaceRequest) + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances(const bool inPlaceRequest) const { containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; return std::move(createRestInstances(instances, inPlaceRequest)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( - containers::ServiceInstanceList &instances, const bool inPlaceRequest) + containers::ServiceInstanceList &instances, const bool inPlaceRequest) const { if (_descriptors.size() > 1) { diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 707680e..3dd4cbe 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -56,10 +56,8 @@ namespace sb::di::details::core protected: IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); - - OneOrList &createRestInstances(const containers::ServiceDescriptorList &descriptors, + OneOrList *createRestInstances(const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index 2f14923..d158037 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -37,8 +37,6 @@ namespace sb::di::details::core containers::ServiceInstancesMap &getSingletons(); - helpers::ScopedGuard spawnGuard(TypeId typeId); - private: void prebuildSingletons(); }; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index c3687b9..e03b8ce 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -16,31 +16,31 @@ namespace sb::di::details::core public: ServiceInstancesResolver(ServiceInstanceCreator &creator, const containers::ServiceDescriptorList &descriptors); - IServiceInstance::Ptr createInstance(); + [[nodiscard]] IServiceInstance::Ptr createInstance() const; - containers::ServiceInstanceList createOneInstance(); + [[nodiscard]] containers::ServiceInstanceList createOneInstance() const; - containers::ServiceInstanceList createAllInstances(); + [[nodiscard]] containers::ServiceInstanceList createAllInstances() const; - containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances); + containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances) const; - IServiceInstance::Ptr createInstanceInPlace(); + [[nodiscard]] IServiceInstance::Ptr createInstanceInPlace() const; - containers::ServiceInstanceList createOneInstanceInPlace(); + [[nodiscard]] containers::ServiceInstanceList createOneInstanceInPlace() const; - containers::ServiceInstanceList createAllInstancesInPlace(); + [[nodiscard]] containers::ServiceInstanceList createAllInstancesInPlace() const; - containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances); + containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; private: - IServiceInstance::Ptr createInstance(bool inPlaceRequest); + [[nodiscard]] IServiceInstance::Ptr createInstance(bool inPlaceRequest) const; - containers::ServiceInstanceList createOneInstance(bool inPlaceRequest); + [[nodiscard]] containers::ServiceInstanceList createOneInstance(bool inPlaceRequest) const; - containers::ServiceInstanceList createAllInstances(bool inPlaceRequest); + [[nodiscard]] containers::ServiceInstanceList createAllInstances(bool inPlaceRequest) const; containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, - bool inPlaceRequest); + bool inPlaceRequest) const; }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index 567e282..a8cf40f 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -66,6 +66,12 @@ namespace sb::di */ virtual IServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) = 0; + /** + * @brief Creates service instances + * @details If service was not registered or was registered as scoped/singleton, method returns null option + */ + virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; + /** * @brief Creates service instance in place, might throw exception * @details If service was not registered or was registered as scoped/singleton, method throws exception @@ -79,12 +85,6 @@ namespace sb::di */ virtual IServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; - /** - * @brief Creates service instances - * @details If service was not registered or was registered as scoped/singleton, method returns null option - */ - virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; - virtual ~IServiceInstanceProvider() = default; }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index a9d2063..dabd815 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -24,6 +24,7 @@ namespace sb::di explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) : _instanceProvider(std::move(instanceProvider)) { + details::utils::Require::notNull(_instanceProvider); getInstanceProvider().init(*this); } @@ -83,21 +84,13 @@ namespace sb::di * @brief Returns inner service instance provider * @throws sb::di::NullPointerException */ - [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const - { - details::utils::Require::notNull(_instanceProvider); - return *_instanceProvider; - } + [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const { return *_instanceProvider; } /** * @brief Returns inner service instance provider * @throws sb::di::NullPointerException */ - IServiceInstanceProvider &getInstanceProvider() - { - details::utils::Require::notNull(_instanceProvider); - return *_instanceProvider; - } + IServiceInstanceProvider &getInstanceProvider() { return *_instanceProvider; } /** * @brief Returns service pointer, might be null From dcceaca45f8e452fcc55ac115fb3e58818ff27a2 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Thu, 25 Jan 2024 21:30:46 +0100 Subject: [PATCH 13/45] code refactor --- .../DI/Details/Core/Impl/ServiceInstanceProvider.hpp | 7 +------ .../DI/Details/Core/ServiceInstanceProvider.hpp | 10 +++++----- Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 2 ++ Include/SevenBit/DI/ServiceLifeTime.hpp | 2 ++ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 01f9999..9de4685 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -16,11 +16,6 @@ namespace sb::di::details::core { - INLINE ServiceInstanceProvider::ServiceInstanceProvider(const ServiceInstanceProvider &provider) - : _options(provider._options), _root(provider._root), _scoped(_options.strongDestructionOrder) - { - } - INLINE ServiceInstanceProvider::ServiceInstanceProvider(ServiceInstanceProviderRoot &root, const ServiceProviderOptions options) : _options(options), _root(root), _scoped(_options.strongDestructionOrder) @@ -36,7 +31,7 @@ namespace sb::di::details::core INLINE IServiceInstanceProvider::Ptr ServiceInstanceProvider::createScope() const { - return IServiceInstanceProvider::Ptr{new ServiceInstanceProvider{*this}}; + return std::make_unique(_root, _options); } INLINE const IServiceInstance &ServiceInstanceProvider::getInstance(const TypeId serviceTypeId) diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 3dd4cbe..36dfb04 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -20,20 +20,20 @@ namespace sb::di::details::core class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; - ServiceInstanceProviderRoot &_root; ServiceInstanceCreator _instanceCreator; + ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; - ServiceInstanceProvider(const ServiceInstanceProvider &provider); - public: using Ptr = std::unique_ptr; - explicit ServiceInstanceProvider(ServiceInstanceProviderRoot &root, ServiceProviderOptions options); + ServiceInstanceProvider(ServiceInstanceProviderRoot &root, ServiceProviderOptions options); - ServiceInstanceProvider(ServiceInstanceProvider &&) noexcept = default; + ServiceInstanceProvider(ServiceInstanceProvider &&) noexcept = delete; + ServiceInstanceProvider(const ServiceInstanceProvider &) = delete; ServiceInstanceProvider &operator=(const ServiceInstanceProvider &) = delete; + ServiceInstanceProvider &operator=(ServiceInstanceProvider &&) = delete; void init(ServiceProvider &serviceProvider) override; diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp index a629a25..011dee6 100644 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp @@ -13,6 +13,8 @@ namespace sb::di INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} + INLINE ServiceLifeTime::Type ServiceLifeTime::getType() const { return _type; } + INLINE bool ServiceLifeTime::is(const Type type) const { return _type == type; } INLINE bool ServiceLifeTime::isSingleton() const { return is(Singleton); } INLINE bool ServiceLifeTime::isScoped() const { return is(Scoped); } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index fcccc4f..a3fe821 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -48,6 +48,8 @@ namespace sb::di ServiceLifeTime &operator=(ServiceLifeTime &&) = default; ServiceLifeTime &operator=(const ServiceLifeTime &) = default; + [[nodiscard]] Type getType() const; + /** * @brief checks if lifetime is given type */ From 23bfbaa80a87ad032f6a3aa23bc29d7915e88d19 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Fri, 26 Jan 2024 21:58:40 +0100 Subject: [PATCH 14/45] code refactor --- .../Containers/ServiceInstanceList.hpp | 3 + .../Core/Impl/ServiceInstanceProvider.hpp | 172 ++++++++++++++---- .../Core/Impl/ServiceInstancesResolver.hpp | 36 ++++ .../Details/Core/ServiceInstanceProvider.hpp | 20 +- .../Details/Core/ServiceInstancesResolver.hpp | 10 + .../DI/Details/Services/AliasService.hpp | 47 +++++ Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 3 +- Include/SevenBit/DI/ServiceLifeTime.hpp | 13 +- 8 files changed, 258 insertions(+), 46 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Services/AliasService.hpp diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index 02b6274..8a2ce4e 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -21,6 +21,9 @@ namespace sb::di::details::containers ServiceInstanceList(const ServiceInstanceList &) = delete; ServiceInstanceList(ServiceInstanceList &&) = default; + ServiceInstanceList &operator=(const ServiceInstanceList &) = delete; + ServiceInstanceList &operator=(ServiceInstanceList &&) = default; + void add(IServiceInstance::Ptr &&service); OneOrList &getInnerList(); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 9de4685..7bebae3 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -46,28 +46,16 @@ namespace sb::di::details::core INLINE const IServiceInstance *ServiceInstanceProvider::tryGetInstance(const TypeId serviceTypeId) { - if (const auto instances = findRegisteredInstances(serviceTypeId)) - { - return instances->last().get(); - } - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; + return tryGetInstanceWithLifeTime(serviceTypeId).first; } INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { - const auto instances = findRegisteredInstances(serviceTypeId); - if (!instances) + if (auto [instances, _] = tryGetInstancesWithLifeTime(serviceTypeId); instances) { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; + return &instances->getInnerList(); } - if (!instances->isSealed()) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? createRestInstances(*descriptors, *instances) : nullptr; - } - return &instances->getInnerList(); + return nullptr; } INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) @@ -82,8 +70,7 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId); - descriptors && descriptors->getLifeTime().isTransient()) + if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { return makeResolver(*descriptors).createInstance(); } @@ -93,8 +80,7 @@ namespace sb::di::details::core INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId); - descriptors && descriptors->getLifeTime().isTransient()) + if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { auto instances = makeResolver(*descriptors).createAllInstances(); return std::move(instances.getInnerList()); @@ -115,9 +101,8 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId); - descriptors && descriptors->getLifeTime().isTransient() && - descriptors->last().getImplementationTypeId() == serviceTypeId) + if (const auto descriptors = findTransientDescriptors(serviceTypeId); + descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) { return makeResolver(*descriptors).createInstanceInPlace(); } @@ -126,40 +111,122 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } - INLINE IServiceInstance *ServiceInstanceProvider::tryCreateAndRegister( - const containers::ServiceDescriptorList &descriptors) + INLINE std::pair ServiceInstanceProvider::tryGetInstanceWithLifeTime( + const TypeId serviceTypeId) { - if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) + if (const auto [instances, lifeTime] = findRegisteredInstances(serviceTypeId); instances) { - auto instance = makeResolver(descriptors).createInstanceInPlace(); - return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); + return {instances->last().get(), lifeTime}; } - return nullptr; + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegister(*descriptors) + : std::pair{nullptr, ServiceLifeTime::scoped()}; + } + + INLINE std::pair ServiceInstanceProvider:: + tryGetInstancesWithLifeTime(const TypeId serviceTypeId) + { + const auto [instances, lifeTime] = findRegisteredInstances(serviceTypeId); + if (!instances) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegisterAll(*descriptors) + : std::pair{ + nullptr, ServiceLifeTime::scoped()}; + } + if (!instances->isSealed()) + { + const auto descriptors = findDescriptors(serviceTypeId); + return descriptors ? createRestInstances(*descriptors, *instances) + : std::pair{ + nullptr, ServiceLifeTime::scoped()}; + } + return {instances, lifeTime}; } - INLINE OneOrList *ServiceInstanceProvider::tryCreateAndRegisterAll( + INLINE std::pair ServiceInstanceProvider::tryCreateAndRegister( const containers::ServiceDescriptorList &descriptors) { - if (const auto instancesMap = tryGetInstancesMap(descriptors.getLifeTime())) + auto lifeTime = descriptors.getLifeTime(); + IServiceInstance::Ptr instance; + if (descriptors.getLifeTime().isAlias()) { - auto instances = makeResolver(descriptors).createAllInstancesInPlace(); - return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); + auto [original, originalLifeTime] = + tryGetInstanceWithLifeTime(descriptors.last().getImplementationTypeId()); + if (original) + { + instance = makeResolver(descriptors).createAlias(*original); + lifeTime = originalLifeTime; + } } - return nullptr; + else + { + instance = makeResolver(descriptors).createInstanceInPlace(); + } + if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instance) + { + return {instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(), lifeTime}; + } + return {nullptr, lifeTime}; } - INLINE OneOrList *ServiceInstanceProvider::createRestInstances( + INLINE std::pair ServiceInstanceProvider:: + tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors) + { + auto lifeTime = descriptors.getLifeTime(); + containers::ServiceInstanceList instances{nullptr}; + if (descriptors.getLifeTime().isAlias()) + { + auto [originals, originalLifeTime] = + tryGetInstancesWithLifeTime(descriptors.last().getImplementationTypeId()); + if (originals) + { + instances = makeResolver(descriptors).createAllAliases(*originals); + lifeTime = originalLifeTime; + } + } + else + { + instances = makeResolver(descriptors).createAllInstancesInPlace(); + } + if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instances.last()) + { + return {&instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)), lifeTime}; + } + return {nullptr, ServiceLifeTime::scoped()}; + } + + INLINE std::pair ServiceInstanceProvider::createRestInstances( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - return &makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); + auto lifeTime = descriptors.getLifeTime(); + if (descriptors.getLifeTime().isAlias()) + { + auto [originals, originalLifeTime] = + tryGetInstancesWithLifeTime(descriptors.last().getImplementationTypeId()); + if (originals) + { + return {&makeResolver(descriptors).createRestAliases(instances, *originals), originalLifeTime}; + } + } + else + { + instances = makeResolver(descriptors).createAllInstancesInPlace(); + } + + return {&makeResolver(descriptors).createRestInstancesInPlace(instances), lifeTime}; } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::findRegisteredInstances(const TypeId serviceTypeId) + INLINE std::pair ServiceInstanceProvider:: + findRegisteredInstances(const TypeId serviceTypeId) { - const auto singletons = _root.getSingletons().findServices(serviceTypeId); - return singletons ? singletons : _scoped.findServices(serviceTypeId); + if (const auto singletons = _root.getSingletons().findServices(serviceTypeId)) + { + return {singletons, ServiceLifeTime::singleton()}; + } + return {_scoped.findServices(serviceTypeId), ServiceLifeTime::scoped()}; } INLINE containers::ServiceInstancesMap *ServiceInstanceProvider::tryGetInstancesMap(const ServiceLifeTime &lifeTime) @@ -171,6 +238,33 @@ namespace sb::di::details::core return lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped; } + INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findTransientDescriptors( + const TypeId serviceTypeId) const + { + if (const auto descriptors = findDescriptors(serviceTypeId)) + { + if (descriptors->getLifeTime().isAny(ServiceLifeTime::transient(), ServiceLifeTime::alias())) + { + return descriptors; + } + } + return nullptr; + } + + INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findNonTransientDescriptors( + const TypeId serviceTypeId) const + { + if (const auto descriptors = findDescriptors(serviceTypeId)) + { + if (descriptors->getLifeTime().isAny(ServiceLifeTime::singleton(), ServiceLifeTime::scoped(), + ServiceLifeTime::alias())) + { + return descriptors; + } + } + return nullptr; + } + INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors( const TypeId serviceTypeId) const { diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 7c6c93f..eac75b8 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -6,6 +6,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" +#include "SevenBit/DI/Details/Services/AliasService.hpp" namespace sb::di::details::core { @@ -54,6 +55,41 @@ namespace sb::di::details::core return createRestInstances(instances, true); } + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(IServiceInstance &instance) const + { + return std::make_unique(instance.get(), _descriptors.last().getImplementationTypeId()); + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAliase( + containers::ServiceInstanceList &instances) const + { + return containers::ServiceInstanceList{createAlias(*instances.last())}; + } + + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( + containers::ServiceInstanceList &instances) const + { + containers::ServiceInstanceList aliases{createAlias(*instances.first())}; + return std::move(createRestAliases(instances, aliases)); + } + + INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( + containers::ServiceInstanceList &instances, containers::ServiceInstanceList &toFill) const + { + if (instances.size() > 1) + { + auto &list = instances.getInnerList().getAsList(); + toFill.reserve(list.size()); + const auto end = list.end(); + for (auto it = ++list.begin(); it != end; ++it) // skip first and last + { + toFill.add(createAlias(**it)); + } + } + toFill.seal(); + return toFill; + } + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const { return _creator.createInstance(_descriptors.last(), inPlaceRequest); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 36dfb04..bdefa1e 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -24,6 +24,9 @@ namespace sb::di::details::core ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; + using InstanceResult = std::pair; + using InstancesResult = std::pair; + public: using Ptr = std::unique_ptr; @@ -55,15 +58,22 @@ namespace sb::di::details::core [[nodiscard]] const ServiceProviderOptions &getOptions() const override; protected: - IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); - OneOrList *createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); + std::pair tryGetInstanceWithLifeTime(TypeId serviceTypeId); + std::pair tryGetInstancesWithLifeTime(TypeId serviceTypeId); + + std::pair tryCreateAndRegister( + const containers::ServiceDescriptorList &descriptors); + std::pair tryCreateAndRegisterAll( + const containers::ServiceDescriptorList &descriptors); + std::pair createRestInstances( + const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); - containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); + std::pair findRegisteredInstances(TypeId serviceTypeId); + [[nodiscard]] const containers::ServiceDescriptorList *findTransientDescriptors(TypeId serviceTypeId) const; + [[nodiscard]] const containers::ServiceDescriptorList *findNonTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index e03b8ce..9faaa37 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -32,6 +32,16 @@ namespace sb::di::details::core containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; + [[nodiscard]] IServiceInstance::Ptr createAlias(IServiceInstance &instance) const; + + [[nodiscard]] containers::ServiceInstanceList createOneAliase(containers::ServiceInstanceList &instances) const; + + [[nodiscard]] containers::ServiceInstanceList createAllAliases( + containers::ServiceInstanceList &instances) const; + + [[nodiscard]] containers::ServiceInstanceList &createRestAliases(containers::ServiceInstanceList &instances, + containers::ServiceInstanceList &toFill) const; + private: [[nodiscard]] IServiceInstance::Ptr createInstance(bool inPlaceRequest) const; diff --git a/Include/SevenBit/DI/Details/Services/AliasService.hpp b/Include/SevenBit/DI/Details/Services/AliasService.hpp new file mode 100644 index 0000000..c9e1a08 --- /dev/null +++ b/Include/SevenBit/DI/Details/Services/AliasService.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" + +namespace sb::di::details::services +{ + class AliasService final : public IServiceInstance + { + void *_service = nullptr; + const TypeId _serviceTypeId; + + public: + using Ptr = std::unique_ptr; + + explicit AliasService(void *service, const TypeId serviceTypeId) + : _service(service), _serviceTypeId(serviceTypeId) + { + } + + AliasService(const AliasService &) = default; + AliasService(AliasService &&) = default; + + AliasService &operator=(const AliasService &) = default; + AliasService &operator=(AliasService &&) = default; + + [[nodiscard]] void *get() const override { return _service; } + + void *getForMoveOut() override + { + throw CannotMoveOutServiceException{getTypeId(), "Alias service cannot be moved out"}; + } + + void *release() override + { + throw CannotReleaseServiceException{getTypeId(), "Alias service ownership cannot be released"}; + } + + [[nodiscard]] TypeId getTypeId() const override { return _serviceTypeId; } + + [[nodiscard]] bool isValid() const override { return _service != nullptr; } + }; +} // namespace sb::di::details::services diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp index 011dee6..f5d2203 100644 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp @@ -10,8 +10,9 @@ namespace sb::di INLINE ServiceLifeTime ServiceLifeTime::singleton() { return ServiceLifeTime{Singleton}; } INLINE ServiceLifeTime ServiceLifeTime::scoped() { return ServiceLifeTime{Scoped}; } INLINE ServiceLifeTime ServiceLifeTime::transient() { return ServiceLifeTime{Transient}; } + INLINE ServiceLifeTime ServiceLifeTime::alias() { return ServiceLifeTime{Alias}; } - INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} + INLINE constexpr ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} INLINE ServiceLifeTime::Type ServiceLifeTime::getType() const { return _type; } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index a3fe821..b112217 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -36,11 +36,12 @@ namespace sb::di * @brief creates transient service lifetime */ static ServiceLifeTime transient(); + static ServiceLifeTime alias(); /** * @brief Construct a new Service Life Time object with specified type */ - explicit ServiceLifeTime(Type type); + constexpr explicit ServiceLifeTime(Type type); ServiceLifeTime(ServiceLifeTime &&) = default; ServiceLifeTime(const ServiceLifeTime &) = default; @@ -71,6 +72,16 @@ namespace sb::di */ [[nodiscard]] bool isAlias() const; + template [[nodiscard]] bool isAny(TServiceLifeTime... types) const + { + return ((*this == types) || ...); + } + + template [[nodiscard]] bool isNot(TServiceLifeTime... types) const + { + return ((*this != types) && ...); + } + bool operator!=(const ServiceLifeTime &scope) const; bool operator==(const ServiceLifeTime &scope) const; }; From 874a8111ab89f3094bf823f0ebbde77a858e3d57 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 27 Jan 2024 13:16:34 +0100 Subject: [PATCH 15/45] add alias handling implementation --- .../Core/Impl/ServiceInstanceProvider.hpp | 114 ++++++------------ .../Core/Impl/ServiceInstancesResolver.hpp | 10 +- .../Details/Core/ServiceInstanceProvider.hpp | 15 +-- .../Details/Core/ServiceInstancesResolver.hpp | 11 +- Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 2 +- Include/SevenBit/DI/ServiceLifeTime.hpp | 2 +- 6 files changed, 58 insertions(+), 96 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 7bebae3..ba98fc1 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -46,16 +46,28 @@ namespace sb::di::details::core INLINE const IServiceInstance *ServiceInstanceProvider::tryGetInstance(const TypeId serviceTypeId) { - return tryGetInstanceWithLifeTime(serviceTypeId).first; + if (const auto instances = findRegisteredInstances(serviceTypeId)) + { + return instances->last().get(); + } + const auto descriptors = findNonTransientDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; } INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { - if (auto [instances, _] = tryGetInstancesWithLifeTime(serviceTypeId); instances) + const auto instances = findRegisteredInstances(serviceTypeId); + if (!instances) { - return &instances->getInnerList(); + const auto descriptors = findNonTransientDescriptors(serviceTypeId); + return descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; } - return nullptr; + if (!instances->isSealed()) + { + const auto descriptors = findNonTransientDescriptors(serviceTypeId); + return descriptors ? createRestInstances(*descriptors, *instances) : nullptr; + } + return &instances->getInnerList(); } INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) @@ -111,52 +123,18 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } - INLINE std::pair ServiceInstanceProvider::tryGetInstanceWithLifeTime( - const TypeId serviceTypeId) - { - if (const auto [instances, lifeTime] = findRegisteredInstances(serviceTypeId); instances) - { - return {instances->last().get(), lifeTime}; - } - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegister(*descriptors) - : std::pair{nullptr, ServiceLifeTime::scoped()}; - } - - INLINE std::pair ServiceInstanceProvider:: - tryGetInstancesWithLifeTime(const TypeId serviceTypeId) - { - const auto [instances, lifeTime] = findRegisteredInstances(serviceTypeId); - if (!instances) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegisterAll(*descriptors) - : std::pair{ - nullptr, ServiceLifeTime::scoped()}; - } - if (!instances->isSealed()) - { - const auto descriptors = findDescriptors(serviceTypeId); - return descriptors ? createRestInstances(*descriptors, *instances) - : std::pair{ - nullptr, ServiceLifeTime::scoped()}; - } - return {instances, lifeTime}; - } - - INLINE std::pair ServiceInstanceProvider::tryCreateAndRegister( + INLINE IServiceInstance *ServiceInstanceProvider::tryCreateAndRegister( const containers::ServiceDescriptorList &descriptors) { auto lifeTime = descriptors.getLifeTime(); IServiceInstance::Ptr instance; - if (descriptors.getLifeTime().isAlias()) + if (lifeTime.isAlias()) { - auto [original, originalLifeTime] = - tryGetInstanceWithLifeTime(descriptors.last().getImplementationTypeId()); - if (original) + const auto aliasTypeId = descriptors.last().getImplementationTypeId(); + if (const auto original = tryGetInstance(aliasTypeId)) { instance = makeResolver(descriptors).createAlias(*original); - lifeTime = originalLifeTime; + lifeTime = _scoped.contains(aliasTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); } } else @@ -165,68 +143,56 @@ namespace sb::di::details::core } if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instance) { - return {instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(), lifeTime}; + return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); } - return {nullptr, lifeTime}; + return nullptr; } - INLINE std::pair ServiceInstanceProvider:: - tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors) + INLINE OneOrList *ServiceInstanceProvider::tryCreateAndRegisterAll( + const containers::ServiceDescriptorList &descriptors) { auto lifeTime = descriptors.getLifeTime(); containers::ServiceInstanceList instances{nullptr}; - if (descriptors.getLifeTime().isAlias()) + if (lifeTime.isAlias()) { - auto [originals, originalLifeTime] = - tryGetInstancesWithLifeTime(descriptors.last().getImplementationTypeId()); - if (originals) + const auto aliasTypeId = descriptors.last().getImplementationTypeId(); + if (const auto originals = tryGetInstances(aliasTypeId)) { instances = makeResolver(descriptors).createAllAliases(*originals); - lifeTime = originalLifeTime; + lifeTime = _scoped.contains(aliasTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); } } else { instances = makeResolver(descriptors).createAllInstancesInPlace(); } - if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instances.last()) + if (const auto instancesMap = tryGetInstancesMap(lifeTime)) { - return {&instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)), lifeTime}; + return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); } - return {nullptr, ServiceLifeTime::scoped()}; + return nullptr; } - INLINE std::pair ServiceInstanceProvider::createRestInstances( + INLINE OneOrList *ServiceInstanceProvider::createRestInstances( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - auto lifeTime = descriptors.getLifeTime(); if (descriptors.getLifeTime().isAlias()) { - auto [originals, originalLifeTime] = - tryGetInstancesWithLifeTime(descriptors.last().getImplementationTypeId()); - if (originals) + const auto aliasTypeId = descriptors.last().getImplementationTypeId(); + if (const auto originals = tryGetInstances(aliasTypeId)) { - return {&makeResolver(descriptors).createRestAliases(instances, *originals), originalLifeTime}; + return &makeResolver(descriptors).createRestAliases(*originals, instances).getInnerList(); } } - else - { - instances = makeResolver(descriptors).createAllInstancesInPlace(); - } - - return {&makeResolver(descriptors).createRestInstancesInPlace(instances), lifeTime}; + return &makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } - INLINE std::pair ServiceInstanceProvider:: - findRegisteredInstances(const TypeId serviceTypeId) + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::findRegisteredInstances(const TypeId serviceTypeId) { - if (const auto singletons = _root.getSingletons().findServices(serviceTypeId)) - { - return {singletons, ServiceLifeTime::singleton()}; - } - return {_scoped.findServices(serviceTypeId), ServiceLifeTime::scoped()}; + const auto singletons = _root.getSingletons().findServices(serviceTypeId); + return singletons ? singletons : _scoped.findServices(serviceTypeId); } INLINE containers::ServiceInstancesMap *ServiceInstanceProvider::tryGetInstancesMap(const ServiceLifeTime &lifeTime) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index eac75b8..42676c4 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -55,30 +55,30 @@ namespace sb::di::details::core return createRestInstances(instances, true); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(IServiceInstance &instance) const + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance &instance) const { return std::make_unique(instance.get(), _descriptors.last().getImplementationTypeId()); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAliase( - containers::ServiceInstanceList &instances) const + const OneOrList &instances) const { return containers::ServiceInstanceList{createAlias(*instances.last())}; } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( - containers::ServiceInstanceList &instances) const + const OneOrList &instances) const { containers::ServiceInstanceList aliases{createAlias(*instances.first())}; return std::move(createRestAliases(instances, aliases)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( - containers::ServiceInstanceList &instances, containers::ServiceInstanceList &toFill) const + const OneOrList &instances, containers::ServiceInstanceList &toFill) const { if (instances.size() > 1) { - auto &list = instances.getInnerList().getAsList(); + auto &list = instances.getAsList(); toFill.reserve(list.size()); const auto end = list.end(); for (auto it = ++list.begin(); it != end; ++it) // skip first and last diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index bdefa1e..5a8fbab 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -58,19 +58,14 @@ namespace sb::di::details::core [[nodiscard]] const ServiceProviderOptions &getOptions() const override; protected: - std::pair tryGetInstanceWithLifeTime(TypeId serviceTypeId); - std::pair tryGetInstancesWithLifeTime(TypeId serviceTypeId); - - std::pair tryCreateAndRegister( - const containers::ServiceDescriptorList &descriptors); - std::pair tryCreateAndRegisterAll( - const containers::ServiceDescriptorList &descriptors); - std::pair createRestInstances( - const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); + IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); + OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); + OneOrList *createRestInstances(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); - std::pair findRegisteredInstances(TypeId serviceTypeId); + containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); [[nodiscard]] const containers::ServiceDescriptorList *findTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findNonTransientDescriptors(TypeId serviceTypeId) const; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index 9faaa37..d7db14b 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -32,15 +32,16 @@ namespace sb::di::details::core containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; - [[nodiscard]] IServiceInstance::Ptr createAlias(IServiceInstance &instance) const; + [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance &instance) const; - [[nodiscard]] containers::ServiceInstanceList createOneAliase(containers::ServiceInstanceList &instances) const; + [[nodiscard]] containers::ServiceInstanceList createOneAliase( + const OneOrList &instances) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( - containers::ServiceInstanceList &instances) const; + const OneOrList &instances) const; - [[nodiscard]] containers::ServiceInstanceList &createRestAliases(containers::ServiceInstanceList &instances, - containers::ServiceInstanceList &toFill) const; + [[nodiscard]] containers::ServiceInstanceList &createRestAliases( + const OneOrList &instances, containers::ServiceInstanceList &toFill) const; private: [[nodiscard]] IServiceInstance::Ptr createInstance(bool inPlaceRequest) const; diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp index f5d2203..eb821d0 100644 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp @@ -12,7 +12,7 @@ namespace sb::di INLINE ServiceLifeTime ServiceLifeTime::transient() { return ServiceLifeTime{Transient}; } INLINE ServiceLifeTime ServiceLifeTime::alias() { return ServiceLifeTime{Alias}; } - INLINE constexpr ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} + INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} INLINE ServiceLifeTime::Type ServiceLifeTime::getType() const { return _type; } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index b112217..f47c857 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -41,7 +41,7 @@ namespace sb::di /** * @brief Construct a new Service Life Time object with specified type */ - constexpr explicit ServiceLifeTime(Type type); + explicit ServiceLifeTime(Type type); ServiceLifeTime(ServiceLifeTime &&) = default; ServiceLifeTime(const ServiceLifeTime &) = default; From 057406cd51ea5406f1924a94635d5c0c8e019824 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 27 Jan 2024 14:56:08 +0100 Subject: [PATCH 16/45] improve alias code --- .../Core/Impl/ServiceInstanceProvider.hpp | 31 ++++++++++--------- .../Details/Core/ServiceInstanceProvider.hpp | 8 ++--- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index ba98fc1..18a1e0b 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -46,28 +46,29 @@ namespace sb::di::details::core INLINE const IServiceInstance *ServiceInstanceProvider::tryGetInstance(const TypeId serviceTypeId) { - if (const auto instances = findRegisteredInstances(serviceTypeId)) + auto instances = findRegisteredInstances(serviceTypeId); + if (!instances) { - return instances->last().get(); + const auto descriptors = findNonTransientDescriptors(serviceTypeId); + instances = descriptors ? tryCreateAndRegister(*descriptors) : nullptr; } - const auto descriptors = findNonTransientDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegister(*descriptors) : nullptr; + return instances ? instances->last().get() : nullptr; } INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { - const auto instances = findRegisteredInstances(serviceTypeId); + auto instances = findRegisteredInstances(serviceTypeId); if (!instances) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - return descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; + instances = descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; } - if (!instances->isSealed()) + else if (!instances->isSealed()) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - return descriptors ? createRestInstances(*descriptors, *instances) : nullptr; + instances = descriptors ? createRestInstances(*descriptors, *instances) : nullptr; } - return &instances->getInnerList(); + return instances ? &instances->getInnerList() : nullptr; } INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) @@ -123,7 +124,7 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } - INLINE IServiceInstance *ServiceInstanceProvider::tryCreateAndRegister( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryCreateAndRegister( const containers::ServiceDescriptorList &descriptors) { auto lifeTime = descriptors.getLifeTime(); @@ -143,12 +144,12 @@ namespace sb::di::details::core } if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instance) { - return instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)).last().get(); + return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)); } return nullptr; } - INLINE OneOrList *ServiceInstanceProvider::tryCreateAndRegisterAll( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryCreateAndRegisterAll( const containers::ServiceDescriptorList &descriptors) { auto lifeTime = descriptors.getLifeTime(); @@ -168,12 +169,12 @@ namespace sb::di::details::core } if (const auto instancesMap = tryGetInstancesMap(lifeTime)) { - return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)).getInnerList(); + return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)); } return nullptr; } - INLINE OneOrList *ServiceInstanceProvider::createRestInstances( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRestInstances( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { if (descriptors.getLifeTime().isAlias()) @@ -184,7 +185,7 @@ namespace sb::di::details::core return &makeResolver(descriptors).createRestAliases(*originals, instances).getInnerList(); } } - return &makeResolver(descriptors).createRestInstancesInPlace(instances).getInnerList(); + return &makeResolver(descriptors).createRestInstancesInPlace(instances); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 5a8fbab..ea302b0 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -58,10 +58,10 @@ namespace sb::di::details::core [[nodiscard]] const ServiceProviderOptions &getOptions() const override; protected: - IServiceInstance *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - OneOrList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); - OneOrList *createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); + containers::ServiceInstanceList *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); + containers::ServiceInstanceList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); + containers::ServiceInstanceList *createRestInstances(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); From c5e39cecb26b13d1eedb030e3095b4e55b138705 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 27 Jan 2024 16:02:14 +0100 Subject: [PATCH 17/45] fix alias handling implementation --- .../Core/Impl/ServiceInstanceProvider.hpp | 87 ++++++++++--------- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 2 +- .../Core/Impl/ServiceInstancesResolver.hpp | 6 +- .../Details/Core/ServiceInstanceProvider.hpp | 12 ++- .../Details/Core/ServiceInstancesResolver.hpp | 3 +- 5 files changed, 60 insertions(+), 50 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 18a1e0b..6cbe847 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -50,7 +50,7 @@ namespace sb::di::details::core if (!instances) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? tryCreateAndRegister(*descriptors) : nullptr; + instances = descriptors ? tryRegister(*descriptors, tryCreate(*descriptors)) : nullptr; } return instances ? instances->last().get() : nullptr; } @@ -61,12 +61,12 @@ namespace sb::di::details::core if (!instances) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? tryCreateAndRegisterAll(*descriptors) : nullptr; + instances = descriptors ? tryRegister(*descriptors, tryCreateAll(*descriptors)) : nullptr; } else if (!instances->isSealed()) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? createRestInstances(*descriptors, *instances) : nullptr; + instances = descriptors ? &createRest(*descriptors, *instances) : nullptr; } return instances ? &instances->getInnerList() : nullptr; } @@ -85,6 +85,10 @@ namespace sb::di::details::core { if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { + if (descriptors->getLifeTime().isAlias()) + { + return tryCreateInstance(descriptors->last().getImplementationTypeId()); + } return makeResolver(*descriptors).createInstance(); } return nullptr; @@ -95,6 +99,10 @@ namespace sb::di::details::core { if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { + if (descriptors->getLifeTime().isAlias()) + { + return tryCreateInstances(descriptors->last().getImplementationTypeId()); + } auto instances = makeResolver(*descriptors).createAllInstances(); return std::move(instances.getInnerList()); } @@ -124,68 +132,67 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryCreateAndRegister( + INLINE std::optional ServiceInstanceProvider::tryCreate( const containers::ServiceDescriptorList &descriptors) { - auto lifeTime = descriptors.getLifeTime(); - IServiceInstance::Ptr instance; - if (lifeTime.isAlias()) + if (descriptors.getLifeTime().isAlias()) { const auto aliasTypeId = descriptors.last().getImplementationTypeId(); if (const auto original = tryGetInstance(aliasTypeId)) { - instance = makeResolver(descriptors).createAlias(*original); - lifeTime = _scoped.contains(aliasTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); + return makeResolver(descriptors).createOneAlias(*original); } + return std::nullopt; } - else - { - instance = makeResolver(descriptors).createInstanceInPlace(); - } - if (const auto instancesMap = tryGetInstancesMap(lifeTime); instancesMap && instance) - { - return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instance)); - } - return nullptr; + return makeResolver(descriptors).createOneInstanceInPlace(); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryCreateAndRegisterAll( + INLINE std::optional ServiceInstanceProvider::tryCreateAll( const containers::ServiceDescriptorList &descriptors) { - auto lifeTime = descriptors.getLifeTime(); - containers::ServiceInstanceList instances{nullptr}; - if (lifeTime.isAlias()) + if (descriptors.getLifeTime().isAlias()) { - const auto aliasTypeId = descriptors.last().getImplementationTypeId(); - if (const auto originals = tryGetInstances(aliasTypeId)) + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + if (const auto originals = tryGetInstances(originalTypeId)) { - instances = makeResolver(descriptors).createAllAliases(*originals); - lifeTime = _scoped.contains(aliasTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); + return makeResolver(descriptors).createAllAliases(*originals); } + return std::nullopt; } - else - { - instances = makeResolver(descriptors).createAllInstancesInPlace(); - } - if (const auto instancesMap = tryGetInstancesMap(lifeTime)) - { - return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(instances)); - } - return nullptr; + return makeResolver(descriptors).createAllInstancesInPlace(); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRestInstances( + INLINE containers::ServiceInstanceList &ServiceInstanceProvider::createRest( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { if (descriptors.getLifeTime().isAlias()) { - const auto aliasTypeId = descriptors.last().getImplementationTypeId(); - if (const auto originals = tryGetInstances(aliasTypeId)) + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + if (const auto originals = tryGetInstances(originalTypeId)) + { + return makeResolver(descriptors).createRestAliases(*originals, instances); + } + } + return makeResolver(descriptors).createRestInstancesInPlace(instances); + } + + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegister( + const containers::ServiceDescriptorList &descriptors, std::optional instances) + { + if (instances) + { + auto lifeTime = descriptors.getLifeTime(); + if (lifeTime.isAlias()) { - return &makeResolver(descriptors).createRestAliases(*originals, instances).getInnerList(); + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); + } + if (const auto instancesMap = tryGetInstancesMap(lifeTime)) + { + return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(*instances)); } } - return &makeResolver(descriptors).createRestInstancesInPlace(instances); + return nullptr; } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index 1110c64..4dc184f 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -28,7 +28,7 @@ namespace sb::di::details::core { if (descriptors.getLifeTime().isSingleton()) { - tryCreateAndRegisterAll(descriptors); + tryRegister(descriptors, tryCreateAll(descriptors)); } } } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 42676c4..59da34a 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -60,10 +60,10 @@ namespace sb::di::details::core return std::make_unique(instance.get(), _descriptors.last().getImplementationTypeId()); } - INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAliase( - const OneOrList &instances) const + INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAlias( + const IServiceInstance &instance) const { - return containers::ServiceInstanceList{createAlias(*instances.last())}; + return containers::ServiceInstanceList{createAlias(instance)}; } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index ea302b0..2b93a0a 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -58,15 +58,19 @@ namespace sb::di::details::core [[nodiscard]] const ServiceProviderOptions &getOptions() const override; protected: - containers::ServiceInstanceList *tryCreateAndRegister(const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList *tryCreateAndRegisterAll(const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList *createRestInstances(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); + std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); + std::optional tryCreateAll( + const containers::ServiceDescriptorList &descriptors); + containers::ServiceInstanceList &createRest(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances); containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); + containers::ServiceInstanceList *tryRegister(const containers::ServiceDescriptorList &descriptors, + std::optional instances); + [[nodiscard]] const containers::ServiceDescriptorList *findTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findNonTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index d7db14b..34db34a 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -34,8 +34,7 @@ namespace sb::di::details::core [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance &instance) const; - [[nodiscard]] containers::ServiceInstanceList createOneAliase( - const OneOrList &instances) const; + [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance &instance) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( const OneOrList &instances) const; From a12b65188da5fbac4cd712e1a15a1968779adba6 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 27 Jan 2024 16:08:43 +0100 Subject: [PATCH 18/45] fix alias handling implementation --- .../DI/Details/Core/Impl/ServiceInstanceProvider.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 6cbe847..874cd8b 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -137,8 +137,7 @@ namespace sb::di::details::core { if (descriptors.getLifeTime().isAlias()) { - const auto aliasTypeId = descriptors.last().getImplementationTypeId(); - if (const auto original = tryGetInstance(aliasTypeId)) + if (const auto original = tryGetInstance(descriptors.last().getImplementationTypeId())) { return makeResolver(descriptors).createOneAlias(*original); } @@ -152,8 +151,7 @@ namespace sb::di::details::core { if (descriptors.getLifeTime().isAlias()) { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); - if (const auto originals = tryGetInstances(originalTypeId)) + if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) { return makeResolver(descriptors).createAllAliases(*originals); } @@ -167,8 +165,7 @@ namespace sb::di::details::core { if (descriptors.getLifeTime().isAlias()) { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); - if (const auto originals = tryGetInstances(originalTypeId)) + if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) { return makeResolver(descriptors).createRestAliases(*originals, instances); } From c63847e5b459c4121082d1d0b652ee3108c81bab Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 27 Jan 2024 21:31:54 +0100 Subject: [PATCH 19/45] improve alias code --- .../Core/Impl/ServiceInstanceProvider.hpp | 36 ++++++------- .../Core/Impl/ServiceInstancesResolver.hpp | 7 ++- .../Details/Core/ServiceInstanceProvider.hpp | 2 +- Include/SevenBit/DI/Details/Utils/Check.hpp | 2 +- Include/SevenBit/DI/Details/Utils/Require.hpp | 4 +- Include/SevenBit/DI/Impl/ServiceLifeTime.hpp | 27 ---------- Include/SevenBit/DI/ServiceDescriber.hpp | 23 ++++----- Include/SevenBit/DI/ServiceLifeTime.hpp | 50 +++++++++---------- Include/SevenBit/DI/ServiceLifeTimes.hpp | 16 ++++++ Source/Source.cpp | 1 - 10 files changed, 75 insertions(+), 93 deletions(-) delete mode 100644 Include/SevenBit/DI/Impl/ServiceLifeTime.hpp create mode 100644 Include/SevenBit/DI/ServiceLifeTimes.hpp diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 874cd8b..82a7328 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -11,6 +11,7 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceLifeTimes.hpp" #include "SevenBit/DI/ServiceProvider.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" @@ -176,20 +177,17 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegister( const containers::ServiceDescriptorList &descriptors, std::optional instances) { - if (instances) + if (!instances) { - auto lifeTime = descriptors.getLifeTime(); - if (lifeTime.isAlias()) - { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); - lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTime::scoped() : ServiceLifeTime::singleton(); - } - if (const auto instancesMap = tryGetInstancesMap(lifeTime)) - { - return &instancesMap->insert(descriptors.getServiceTypeId(), std::move(*instances)); - } + return nullptr; } - return nullptr; + auto lifeTime = descriptors.getLifeTime(); + if (lifeTime.isAlias()) + { + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; + } + return &getInstancesMap(lifeTime).insert(descriptors.getServiceTypeId(), std::move(*instances)); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -200,13 +198,9 @@ namespace sb::di::details::core return singletons ? singletons : _scoped.findServices(serviceTypeId); } - INLINE containers::ServiceInstancesMap *ServiceInstanceProvider::tryGetInstancesMap(const ServiceLifeTime &lifeTime) + INLINE containers::ServiceInstancesMap &ServiceInstanceProvider::getInstancesMap(const ServiceLifeTime &lifeTime) { - if (lifeTime.isTransient()) - { - return nullptr; - } - return lifeTime.isSingleton() ? &_root.getSingletons() : &_scoped; + return lifeTime.isSingleton() ? _root.getSingletons() : _scoped; } INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findTransientDescriptors( @@ -214,7 +208,7 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAny(ServiceLifeTime::transient(), ServiceLifeTime::alias())) + if (descriptors->getLifeTime().isAny(ServiceLifeTimes::Transient, ServiceLifeTimes::Alias)) { return descriptors; } @@ -227,8 +221,8 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAny(ServiceLifeTime::singleton(), ServiceLifeTime::scoped(), - ServiceLifeTime::alias())) + if (descriptors->getLifeTime().isAny(ServiceLifeTimes::Singleton, ServiceLifeTimes::Scoped, + ServiceLifeTimes::Alias)) { return descriptors; } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 59da34a..4ce2818 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -69,7 +69,7 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( const OneOrList &instances) const { - containers::ServiceInstanceList aliases{createAlias(*instances.first())}; + containers::ServiceInstanceList aliases{createAlias(*instances.last())}; return std::move(createRestAliases(instances, aliases)); } @@ -80,11 +80,14 @@ namespace sb::di::details::core { auto &list = instances.getAsList(); toFill.reserve(list.size()); - const auto end = list.end(); + auto realFirst = createAlias(*list.front()); + const auto end = --list.end(); for (auto it = ++list.begin(); it != end; ++it) // skip first and last { toFill.add(createAlias(**it)); } + toFill.add(std::move(realFirst)); + toFill.first().swap(toFill.last()); } toFill.seal(); return toFill; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 2b93a0a..19908f3 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -64,7 +64,7 @@ namespace sb::di::details::core containers::ServiceInstanceList &createRest(const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); - containers::ServiceInstancesMap *tryGetInstancesMap(const ServiceLifeTime &lifeTime); + containers::ServiceInstancesMap &getInstancesMap(const ServiceLifeTime &lifeTime); containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 5b7fa2a..6b72192 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -15,7 +15,7 @@ namespace sb::di::details::utils template static bool notNull(const T *ptr) { return ptr != nullptr; } - template static bool enumValidity(TEnum value) + template constexpr static bool enumValidity(TEnum value) { return std::is_enum_v && value >= 0 && value < TEnum::Count; } diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index 5da8886..28d7fd5 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -53,13 +53,13 @@ namespace sb::di::details::utils } } - template static TEnum validEnumAndGet(TEnum value) + template constexpr static TEnum validEnumAndGet(TEnum value) { validEnum(value); return value; } - template static void validEnum(TEnum value) + template constexpr static void validEnum(TEnum value) { if (!Check::enumValidity(value)) { diff --git a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp b/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp deleted file mode 100644 index eb821d0..0000000 --- a/Include/SevenBit/DI/Impl/ServiceLifeTime.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" - -namespace sb::di -{ - INLINE ServiceLifeTime ServiceLifeTime::singleton() { return ServiceLifeTime{Singleton}; } - INLINE ServiceLifeTime ServiceLifeTime::scoped() { return ServiceLifeTime{Scoped}; } - INLINE ServiceLifeTime ServiceLifeTime::transient() { return ServiceLifeTime{Transient}; } - INLINE ServiceLifeTime ServiceLifeTime::alias() { return ServiceLifeTime{Alias}; } - - INLINE ServiceLifeTime::ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} - - INLINE ServiceLifeTime::Type ServiceLifeTime::getType() const { return _type; } - - INLINE bool ServiceLifeTime::is(const Type type) const { return _type == type; } - INLINE bool ServiceLifeTime::isSingleton() const { return is(Singleton); } - INLINE bool ServiceLifeTime::isScoped() const { return is(Scoped); } - INLINE bool ServiceLifeTime::isTransient() const { return is(Transient); } - INLINE bool ServiceLifeTime::isAlias() const { return is(Alias); } - - INLINE bool ServiceLifeTime::operator==(const ServiceLifeTime &scope) const { return _type == scope._type; } - INLINE bool ServiceLifeTime::operator!=(const ServiceLifeTime &scope) const { return _type != scope._type; } -} // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 805cdf8..3e67590 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -15,7 +15,7 @@ #include "SevenBit/DI/Details/Utils/IsPtr.hpp" #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" +#include "SevenBit/DI/ServiceLifeTimes.hpp" namespace sb::di { @@ -41,7 +41,7 @@ namespace sb::di */ template static ServiceDescriptor describeSingleton() { - return describe(ServiceLifeTime::singleton()); + return describe(ServiceLifeTimes::Singleton); } /** @@ -63,7 +63,7 @@ namespace sb::di */ template static ServiceDescriptor describeScoped() { - return describe(ServiceLifeTime::scoped()); + return describe(ServiceLifeTimes::Scoped); } /** * @brief Creates service descriptor @@ -84,7 +84,7 @@ namespace sb::di */ template static ServiceDescriptor describeTransient() { - return describe(ServiceLifeTime::transient()); + return describe(ServiceLifeTimes::Transient); } /** @@ -164,7 +164,7 @@ namespace sb::di { details::utils::Assert::inheritance(); auto factory = std::make_unique>(service); - return {typeid(TService), ServiceLifeTime::singleton(), std::move(factory)}; + return {typeid(TService), ServiceLifeTimes::Singleton, std::move(factory)}; } /** @@ -187,7 +187,7 @@ namespace sb::di */ template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::singleton(), + return describeFrom(ServiceLifeTimes::Singleton, std::forward(factory)); } /** @@ -210,7 +210,7 @@ namespace sb::di */ template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::scoped(), + return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } /** @@ -233,7 +233,7 @@ namespace sb::di */ template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::transient(), + return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); } @@ -256,7 +256,7 @@ namespace sb::di */ template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::singleton(), + return describeFrom(ServiceLifeTimes::Singleton, std::forward(factory)); } @@ -280,7 +280,7 @@ namespace sb::di template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::scoped(), std::forward(factory)); + return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } /** * @brief Creates service descriptor @@ -302,8 +302,7 @@ namespace sb::di template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTime::transient(), - std::forward(factory)); + return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); } /** diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index f47c857..b5f2582 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -2,9 +2,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" + namespace sb::di { - class EXPORT ServiceLifeTime + class ServiceLifeTime { public: /** @@ -27,67 +29,63 @@ namespace sb::di /** * @brief creates singleton service lifetime */ - static ServiceLifeTime singleton(); + constexpr static ServiceLifeTime singleton() { return ServiceLifeTime{Singleton}; } /** * @brief creates scoped service lifetime */ - static ServiceLifeTime scoped(); + constexpr static ServiceLifeTime scoped() { return ServiceLifeTime{Scoped}; } /** * @brief creates transient service lifetime */ - static ServiceLifeTime transient(); - static ServiceLifeTime alias(); + constexpr static ServiceLifeTime transient() { return ServiceLifeTime{Transient}; } + constexpr static ServiceLifeTime alias() { return ServiceLifeTime{Alias}; } /** * @brief Construct a new Service Life Time object with specified type */ - explicit ServiceLifeTime(Type type); - - ServiceLifeTime(ServiceLifeTime &&) = default; - ServiceLifeTime(const ServiceLifeTime &) = default; + constexpr explicit ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} - ServiceLifeTime &operator=(ServiceLifeTime &&) = default; - ServiceLifeTime &operator=(const ServiceLifeTime &) = default; + constexpr ServiceLifeTime(ServiceLifeTime &&) = default; + constexpr ServiceLifeTime(const ServiceLifeTime &) = default; - [[nodiscard]] Type getType() const; + constexpr ServiceLifeTime &operator=(ServiceLifeTime &&) = default; + constexpr ServiceLifeTime &operator=(const ServiceLifeTime &) = default; /** * @brief checks if lifetime is given type */ - [[nodiscard]] bool is(Type type) const; + [[nodiscard]] constexpr bool is(const Type type) const { return *this == type; } /** * @brief checks if lifetime is singleton */ - [[nodiscard]] bool isSingleton() const; + [[nodiscard]] constexpr bool isSingleton() const { return is(Singleton); } /** * @brief checks if lifetime is scoped */ - [[nodiscard]] bool isScoped() const; + [[nodiscard]] constexpr bool isScoped() const { return is(Scoped); } /** * @brief checks if lifetime is transient */ - [[nodiscard]] bool isTransient() const; + [[nodiscard]] constexpr bool isTransient() const { return is(Transient); } /** * @brief checks if lifetime is alias */ - [[nodiscard]] bool isAlias() const; + [[nodiscard]] constexpr bool isAlias() const { return is(Alias); } - template [[nodiscard]] bool isAny(TServiceLifeTime... types) const + template [[nodiscard]] constexpr bool isAny(TServiceLifeTime... types) const { return ((*this == types) || ...); } - template [[nodiscard]] bool isNot(TServiceLifeTime... types) const + template [[nodiscard]] constexpr bool isNot(TServiceLifeTime... types) const { return ((*this != types) && ...); } - bool operator!=(const ServiceLifeTime &scope) const; - bool operator==(const ServiceLifeTime &scope) const; - }; + constexpr bool operator!=(const ServiceLifeTime &lifeTime) const { return _type != lifeTime._type; } + constexpr bool operator==(const ServiceLifeTime &lifeTime) const { return _type == lifeTime._type; } + constexpr bool operator!=(const Type type) const { return _type != type; } + constexpr bool operator==(const Type type) const { return _type == type; } + }; } // namespace sb::di - -#ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Impl/ServiceLifeTime.hpp" -#endif diff --git a/Include/SevenBit/DI/ServiceLifeTimes.hpp b/Include/SevenBit/DI/ServiceLifeTimes.hpp new file mode 100644 index 0000000..aa79616 --- /dev/null +++ b/Include/SevenBit/DI/ServiceLifeTimes.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/ServiceLifeTime.hpp" + +namespace sb::di +{ + struct ServiceLifeTimes + { + constexpr static ServiceLifeTime Singleton = ServiceLifeTime::singleton(); + constexpr static ServiceLifeTime Scoped = ServiceLifeTime::scoped(); + constexpr static ServiceLifeTime Transient = ServiceLifeTime::transient(); + constexpr static ServiceLifeTime Alias = ServiceLifeTime::alias(); + }; +} // namespace sb::di diff --git a/Source/Source.cpp b/Source/Source.cpp index 8253f23..7bc4f2c 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -16,4 +16,3 @@ #include "SevenBit/DI/Impl/Exceptions.hpp" #include "SevenBit/DI/Impl/ServiceCollection.hpp" #include "SevenBit/DI/Impl/ServiceDescriptor.hpp" -#include "SevenBit/DI/Impl/ServiceLifeTime.hpp" From d3b6d03d0999cb1d34ef10f0fe098f5761fb30a7 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 28 Jan 2024 12:33:24 +0100 Subject: [PATCH 20/45] fix alias handling implementation --- .../Details/Factories/ServiceFcnFactory.hpp | 14 +- .../Factories/UniquePtrServiceFcnFactory.hpp | 3 +- .../Details/Factories/VoidServiceFactory.hpp | 25 +++ Include/SevenBit/DI/Details/Utils/Assert.hpp | 5 + Include/SevenBit/DI/ServiceCollection.hpp | 6 + Include/SevenBit/DI/ServiceDescriber.hpp | 160 +++++++++--------- 6 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index a2f150c..f35cb3d 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -17,29 +17,29 @@ namespace sb::di::details::factories template class ServiceFcnFactory final : public IServiceFactory { using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; - using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; mutable FactoryFcn _factoryFunction; public: + using ServiceType = typename ServiceFactoryInvoker::ReturnType; + explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} { - static_assert(utils::IsInPlaceObjectConstructableV || - utils::notSupportedType, + static_assert(utils::IsInPlaceObjectConstructableV || utils::notSupportedType, "Service factory return type must be copyable or movable"); } - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(FactoryReturnType); } + [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; if (inPlaceRequest) { - return std::make_unique>(invoker.invoke()); + return std::make_unique>(invoker.invoke()); } - auto servicePtr = std::make_unique(invoker.invoke()); - return std::make_unique>(std::move(servicePtr)); + auto servicePtr = std::make_unique(invoker.invoke()); + return std::make_unique>(std::move(servicePtr)); } }; } // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp index 227fd8c..da3f264 100644 --- a/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp @@ -20,11 +20,12 @@ namespace sb::di::details::factories { using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; - using ServiceType = utils::RemoveUniquePtrT; mutable FactoryFcn _factoryFunction; public: + using ServiceType = utils::RemoveUniquePtrT; + explicit UniquePtrServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} { static_assert(utils::IsUniquePtrV || utils::notSupportedType, diff --git a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp new file mode 100644 index 0000000..bc1a03a --- /dev/null +++ b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/IServiceFactory.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di::details::factories +{ + + template class VoidServiceFactory final : public IServiceFactory + { + public: + [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } + + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + { + return nullptr; + } + }; + +} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Utils/Assert.hpp b/Include/SevenBit/DI/Details/Utils/Assert.hpp index 65fcf93..feaaaf1 100644 --- a/Include/SevenBit/DI/Details/Utils/Assert.hpp +++ b/Include/SevenBit/DI/Details/Utils/Assert.hpp @@ -13,5 +13,10 @@ namespace sb::di::details::utils static_assert(std::is_same_v || std::is_base_of_v, "Type TImplementation must inherit from TService"); } + + template static void isNotSame() + { + static_assert(!std::is_same_v, "Type TAlias cannot be same as TService"); + } }; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/ServiceCollection.hpp b/Include/SevenBit/DI/ServiceCollection.hpp index ce71f9e..a625e33 100644 --- a/Include/SevenBit/DI/ServiceCollection.hpp +++ b/Include/SevenBit/DI/ServiceCollection.hpp @@ -449,6 +449,12 @@ namespace sb::di { return add(ServiceDescriber::describeSingleton(service)); } + + template ServiceCollection &addAlias() + { + return add(ServiceDescriber::describeAlias()); + } + /** * @brief Adds service descriptor * @details Adds service descriptor with: diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 3e67590..f2bc536 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -9,10 +9,10 @@ #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp" +#include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" #include "SevenBit/DI/Details/Utils/IsInPlaceObject.hpp" -#include "SevenBit/DI/Details/Utils/IsPtr.hpp" #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" @@ -171,76 +171,73 @@ namespace sb::di * @brief Creates service descriptor * @details Creates service descriptor with: * lifetime - singleton, - * serviceTypeId - typeid(TService), + * serviceTypeId - extracted from factory return type, * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor - * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers, implementation type must inherit from TService + * vectors with pointers or unique pointers * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeSingletonFrom( - * []() { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeSingletonFrom( + * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ - template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) + template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTimes::Singleton, - std::forward(factory)); + return describeFrom(ServiceLifeTimes::Singleton, std::forward(factory)); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: * lifetime - scoped, - * serviceTypeId - typeid(TService), + * serviceTypeId - extracted from factory return type, * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor - * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers, implementation type must inherit from TService + * vectors with pointers or unique pointers * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeScopedFrom( - * []() { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeScopedFrom( + * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ - template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) + + template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTimes::Scoped, - std::forward(factory)); + return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } /** * @brief Creates service descriptor * @details Creates service descriptor with: * lifetime - transient, - * serviceTypeId - typeid(TService), + * serviceTypeId - extracted from factory return type, * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor - * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers, implementation type must inherit from TService + * vectors with pointers or unique pointers * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeTransientFrom( - * []() { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeTransientFrom( + * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ - template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) + + template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTimes::Transient, - std::forward(factory)); + return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); } /** * @brief Creates service descriptor * @details Creates service descriptor with: - * lifetime - singleton, + * lifetime - given service lifetime, * serviceTypeId - extracted from factory return type, * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor @@ -250,82 +247,81 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeSingletonFrom( - * [](const ServiceDescriptor &) { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( + * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); * @endcode */ - template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) + template + static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) { - return describeFrom(ServiceLifeTimes::Singleton, - std::forward(factory)); + return describeFrom(lifetime, std::forward(factoryFcn)); } /** * @brief Creates service descriptor * @details Creates service descriptor with: - * lifetime - scoped, - * serviceTypeId - extracted from factory return type, + * lifetime - singleton, + * serviceTypeId - typeid(TService), * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor + * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers + * vectors with pointers or unique pointers, implementation type must inherit from TService * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeScopedFrom( - * [](const ServiceDescriptor &) { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeSingletonFrom( + * []() { return std::make_unique(); }); * @endcode */ - - template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) + template static ServiceDescriptor describeSingletonFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); + return describeFrom(ServiceLifeTimes::Singleton, std::forward(factory)); } /** * @brief Creates service descriptor * @details Creates service descriptor with: - * lifetime - transient, - * serviceTypeId - extracted from factory return type, + * lifetime - scoped, + * serviceTypeId - typeid(TService), * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor + * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers + * vectors with pointers or unique pointers, implementation type must inherit from TService * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeTransientFrom( - * [](const ServiceDescriptor &) { return std::make_unique(); }); + * ServiceDescriptor descriptor = ServiceDescriber::describeScopedFrom( + * []() { return std::make_unique(); }); * @endcode */ - - template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) + template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { - return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); + return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } - /** * @brief Creates service descriptor * @details Creates service descriptor with: - * lifetime - given service lifetime, - * serviceTypeId - extracted from factory return type, + * lifetime - transient, + * serviceTypeId - typeid(TService), * implementationTypeId - extracted from factory return type, * factory - default factory using FactoryFcn factory functor + * @tparam TService base service type * @tparam FactoryFcn is factory functor with this scheme: (Services...) -> * std::unique_ptr | TImplementation, where services are pointers, unique pointers, references, - * vectors with pointers or unique pointers + * vectors with pointers or unique pointers, implementation type must inherit from TService * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( - * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); + * ServiceDescriptor descriptor = ServiceDescriber::describeTransientFrom( + * []() { return std::make_unique(); }); * @endcode */ - template - static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) + template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { - return describeFrom(lifetime, std::forward(factoryFcn)); + return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); } /** @@ -349,52 +345,54 @@ namespace sb::di template static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) { - return describeFrom(lifetime, std::forward(factoryFcn)); + auto factory = makeFactoryFrom(std::forward(factoryFcn)); + auto serviceTypeId = std::is_void_v ? factory->getServiceTypeId() : TypeId(typeid(TService)); + return {serviceTypeId, lifetime, std::move(factory)}; } - private: - template - static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) + template static ServiceDescriptor describeAlias() { - auto factory = makeFactoryFrom(lifetime, std::forward(factoryFcn)); - auto serviceTypeId = std::is_void_v ? factory->getServiceTypeId() : TypeId(typeid(TService)); - return {serviceTypeId, lifetime, std::move(factory)}; + details::utils::Assert::isNotSame(); + details::utils::Assert::inheritance(); + auto factory = std::make_unique>(); + return {typeid(TAlias), ServiceLifeTimes::Alias, std::move(factory)}; } - template - static IServiceFactory::Ptr makeFactoryFrom(const ServiceLifeTime &lifetime, FactoryFcn &&factoryFcn) + private: + template static IServiceFactory::Ptr makeFactoryFrom(FactoryFcn &&factoryFcn) { using ReturnType = typename details::helpers::ServiceFactoryInvoker::ReturnType; - if constexpr (details::utils::IsPtrV && !AssumeTransient) + if constexpr (details::utils::IsUniquePtrV) { - if (lifetime.isTransient()) - { - throw InjectorException("Service factory cannot return pointer for transient service"); - } - return std::make_unique>( - std::forward(factoryFcn)); - } - else if constexpr (details::utils::IsUniquePtrV) - { - return std::make_unique>( - std::forward(factoryFcn)); + using Factory = details::factories::UniquePtrServiceFcnFactory; + tryCheckFactoryInheritance(); + return std::make_unique(std::forward(factoryFcn)); } else if constexpr (details::utils::IsInPlaceObjectConstructableV) { - return std::make_unique>( - std::forward(factoryFcn)); + using Factory = details::factories::ServiceFcnFactory; + tryCheckFactoryInheritance(); + return std::make_unique(std::forward(factoryFcn)); } else { notSupportedReturnType(); + return nullptr; + } + } + + template static void tryCheckFactoryInheritance() + { + if constexpr (!std::is_void_v) + { + details::utils::Assert::inheritance(); } } template static void notSupportedReturnType() { static_assert(details::utils::notSupportedType, - "Service factory return type must be std::unique_ptr or movable/copyable object or " - "pointer for non transient services"); + "Service factory return type must be std::unique_ptr or movable/copyable object"); } }; } // namespace sb::di From 3534588d74a02ba3bc153edbd3a6c3bdaf156136 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 28 Jan 2024 16:15:49 +0100 Subject: [PATCH 21/45] improve service alias code --- .../Containers/Impl/ServiceDescriptorList.hpp | 24 +++++++-- .../Containers/ServiceDescriptorList.hpp | 5 +- .../Core/Impl/ServiceInstanceCreator.hpp | 9 ++++ .../Core/Impl/ServiceInstanceProvider.hpp | 51 ++++++++++--------- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 2 +- .../Core/Impl/ServiceInstancesResolver.hpp | 12 ++--- .../Details/Core/ServiceInstanceCreator.hpp | 2 + .../Details/Core/ServiceInstanceProvider.hpp | 6 ++- .../Details/Core/ServiceInstancesResolver.hpp | 4 +- Include/SevenBit/DI/Exceptions.hpp | 5 ++ Include/SevenBit/DI/Impl/Exceptions.hpp | 9 ++++ .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 23 ++++++--- Include/SevenBit/DI/ServiceDescriber.hpp | 3 +- Include/SevenBit/DI/ServiceDescriptor.hpp | 11 ++-- Include/SevenBit/DI/ServiceLifeTime.hpp | 11 +--- Include/SevenBit/DI/ServiceLifeTimes.hpp | 1 - 16 files changed, 116 insertions(+), 62 deletions(-) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp index c2a42e4..7a2b6d0 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp @@ -17,8 +17,12 @@ namespace sb::di::details::containers INLINE void ServiceDescriptorList::add(ServiceDescriptor &&descriptor) { - checkBaseType(descriptor); - checkLifeTime(descriptor); + if (!empty()) + { + checkBaseType(descriptor); + checkAlias(descriptor); + checkLifeTime(descriptor); + } _oneOrList.add(std::move(descriptor)); } @@ -30,21 +34,31 @@ namespace sb::di::details::containers INLINE size_t ServiceDescriptorList::size() const { return _oneOrList.size(); } - INLINE const ServiceLifeTime &ServiceDescriptorList::getLifeTime() const { return first().getLifeTime(); } + INLINE ServiceLifeTime ServiceDescriptorList::getLifeTime() const { return first().getLifeTime(); } INLINE TypeId ServiceDescriptorList::getServiceTypeId() const { return first().getServiceTypeId(); } + INLINE bool ServiceDescriptorList::isAlias() const { return first().isAlias(); } + INLINE void ServiceDescriptorList::checkBaseType(const ServiceDescriptor &descriptor) const { - if (!empty() && descriptor.getServiceTypeId() != getServiceTypeId()) + if (descriptor.getServiceTypeId() != getServiceTypeId()) { throw ServiceBaseTypeMismatchException{descriptor.getImplementationTypeId(), getServiceTypeId()}; } } + INLINE void ServiceDescriptorList::checkAlias(const ServiceDescriptor &descriptor) const + { + if (descriptor.isAlias() != isAlias()) + { + throw ServiceAliasMismatchException{descriptor.getImplementationTypeId(), getServiceTypeId(), isAlias()}; + } + } + INLINE void ServiceDescriptorList::checkLifeTime(const ServiceDescriptor &descriptor) const { - if (!empty() && descriptor.getLifeTime() != getLifeTime()) + if (!isAlias() && !descriptor.isAlias() && descriptor.getLifeTime() != getLifeTime()) { throw ServiceLifeTimeMismatchException{descriptor.getImplementationTypeId(), getServiceTypeId()}; } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp index 10088dd..b820657 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp @@ -31,14 +31,17 @@ namespace sb::di::details::containers [[nodiscard]] size_t size() const; - [[nodiscard]] const ServiceLifeTime &getLifeTime() const; + [[nodiscard]] ServiceLifeTime getLifeTime() const; [[nodiscard]] TypeId getServiceTypeId() const; + [[nodiscard]] bool isAlias() const; + void seal(); private: void checkBaseType(const ServiceDescriptor &descriptor) const; + void checkAlias(const ServiceDescriptor &descriptor) const; void checkLifeTime(const ServiceDescriptor &descriptor) const; }; diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 26c9d2b..a07a606 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -6,6 +6,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include namespace sb::di::details::core { @@ -22,4 +23,12 @@ namespace sb::di::details::core auto _ = _guard(descriptor.getImplementationTypeId()); return utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); } + + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(const IServiceInstance *instance, + TypeId serviceTypeId) + { + utils::Require::notNull(instance); + // auto _ = _guard(serviceTypeId); + return std::make_unique(instance->get(), serviceTypeId); + } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 82a7328..11bf8cb 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -67,7 +67,7 @@ namespace sb::di::details::core else if (!instances->isSealed()) { const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? &createRest(*descriptors, *instances) : nullptr; + instances = descriptors ? createRest(*descriptors, *instances) : nullptr; } return instances ? &instances->getInnerList() : nullptr; } @@ -86,7 +86,7 @@ namespace sb::di::details::core { if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAlias()) + if (descriptors->isAlias()) { return tryCreateInstance(descriptors->last().getImplementationTypeId()); } @@ -100,7 +100,7 @@ namespace sb::di::details::core { if (const auto descriptors = findTransientDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAlias()) + if (descriptors->isAlias()) { return tryCreateInstances(descriptors->last().getImplementationTypeId()); } @@ -136,11 +136,11 @@ namespace sb::di::details::core INLINE std::optional ServiceInstanceProvider::tryCreate( const containers::ServiceDescriptorList &descriptors) { - if (descriptors.getLifeTime().isAlias()) + if (descriptors.isAlias()) { if (const auto original = tryGetInstance(descriptors.last().getImplementationTypeId())) { - return makeResolver(descriptors).createOneAlias(*original); + return makeResolver(descriptors).createOneAlias(original); } return std::nullopt; } @@ -150,7 +150,7 @@ namespace sb::di::details::core INLINE std::optional ServiceInstanceProvider::tryCreateAll( const containers::ServiceDescriptorList &descriptors) { - if (descriptors.getLifeTime().isAlias()) + if (descriptors.isAlias()) { if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) { @@ -161,33 +161,37 @@ namespace sb::di::details::core return makeResolver(descriptors).createAllInstancesInPlace(); } - INLINE containers::ServiceInstanceList &ServiceInstanceProvider::createRest( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRest( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - if (descriptors.getLifeTime().isAlias()) + if (descriptors.isAlias()) { if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) { - return makeResolver(descriptors).createRestAliases(*originals, instances); + return &makeResolver(descriptors).createRestAliases(*originals, instances); } + return nullptr; } - return makeResolver(descriptors).createRestInstancesInPlace(instances); + return &makeResolver(descriptors).createRestInstancesInPlace(instances); } INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegister( const containers::ServiceDescriptorList &descriptors, std::optional instances) { - if (!instances) - { - return nullptr; - } - auto lifeTime = descriptors.getLifeTime(); - if (lifeTime.isAlias()) + return instances ? &getInstancesMap(getLifeTime(descriptors)) + .insert(descriptors.getServiceTypeId(), std::move(*instances)) + : nullptr; + } + + INLINE ServiceLifeTime + ServiceInstanceProvider::getLifeTime(const containers::ServiceDescriptorList &descriptors) const + { + if (descriptors.isAlias()) { const auto originalTypeId = descriptors.last().getImplementationTypeId(); - lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; + return _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; } - return &getInstancesMap(lifeTime).insert(descriptors.getServiceTypeId(), std::move(*instances)); + return descriptors.getLifeTime(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -198,7 +202,7 @@ namespace sb::di::details::core return singletons ? singletons : _scoped.findServices(serviceTypeId); } - INLINE containers::ServiceInstancesMap &ServiceInstanceProvider::getInstancesMap(const ServiceLifeTime &lifeTime) + INLINE containers::ServiceInstancesMap &ServiceInstanceProvider::getInstancesMap(const ServiceLifeTime lifeTime) { return lifeTime.isSingleton() ? _root.getSingletons() : _scoped; } @@ -208,7 +212,7 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAny(ServiceLifeTimes::Transient, ServiceLifeTimes::Alias)) + if (descriptors->isAlias() || descriptors->getLifeTime().isTransient()) { return descriptors; } @@ -221,8 +225,8 @@ namespace sb::di::details::core { if (const auto descriptors = findDescriptors(serviceTypeId)) { - if (descriptors->getLifeTime().isAny(ServiceLifeTimes::Singleton, ServiceLifeTimes::Scoped, - ServiceLifeTimes::Alias)) + if (descriptors->isAlias() || + descriptors->getLifeTime().isAny(ServiceLifeTimes::Singleton, ServiceLifeTimes::Scoped)) { return descriptors; } @@ -239,7 +243,8 @@ namespace sb::di::details::core INLINE ServiceInstancesResolver ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { - auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; + auto &creator = descriptors.isAlias() || descriptors.getLifeTime().isSingleton() ? _root._instanceCreator + : _instanceCreator; return ServiceInstancesResolver{creator, descriptors}; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index 4dc184f..cb7ba01 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -26,7 +26,7 @@ namespace sb::di::details::core { for (auto &[_, descriptors] : getDescriptorsMap()) { - if (descriptors.getLifeTime().isSingleton()) + if (!descriptors.isAlias() && descriptors.getLifeTime().isSingleton()) { tryRegister(descriptors, tryCreateAll(descriptors)); } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 4ce2818..732113c 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -55,13 +55,13 @@ namespace sb::di::details::core return createRestInstances(instances, true); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance &instance) const + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance *instance) const { - return std::make_unique(instance.get(), _descriptors.last().getImplementationTypeId()); + return _creator.createInstanceAlias(instance, _descriptors.last().getImplementationTypeId()); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAlias( - const IServiceInstance &instance) const + const IServiceInstance *instance) const { return containers::ServiceInstanceList{createAlias(instance)}; } @@ -69,7 +69,7 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( const OneOrList &instances) const { - containers::ServiceInstanceList aliases{createAlias(*instances.last())}; + containers::ServiceInstanceList aliases{createAlias(instances.last().get())}; return std::move(createRestAliases(instances, aliases)); } @@ -80,11 +80,11 @@ namespace sb::di::details::core { auto &list = instances.getAsList(); toFill.reserve(list.size()); - auto realFirst = createAlias(*list.front()); + auto realFirst = createAlias(list.front().get()); const auto end = --list.end(); for (auto it = ++list.begin(); it != end; ++it) // skip first and last { - toFill.add(createAlias(**it)); + toFill.add(createAlias(it->get())); } toFill.add(std::move(realFirst)); toFill.first().swap(toFill.last()); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index 5726671..c2a36f0 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -16,6 +16,8 @@ namespace sb::di::details::core void setServiceProvider(ServiceProvider &serviceProvider); IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + + IServiceInstance::Ptr createInstanceAlias(const IServiceInstance *instance, TypeId serviceTypeId); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 19908f3..fcea9b8 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -61,16 +61,18 @@ namespace sb::di::details::core std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); std::optional tryCreateAll( const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList &createRest(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList *createRest(const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); - containers::ServiceInstancesMap &getInstancesMap(const ServiceLifeTime &lifeTime); + containers::ServiceInstancesMap &getInstancesMap(ServiceLifeTime lifeTime); containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); containers::ServiceInstanceList *tryRegister(const containers::ServiceDescriptorList &descriptors, std::optional instances); + [[nodiscard]] ServiceLifeTime getLifeTime(const containers::ServiceDescriptorList &descriptors) const; + [[nodiscard]] const containers::ServiceDescriptorList *findTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findNonTransientDescriptors(TypeId serviceTypeId) const; [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index 34db34a..91aed6b 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -32,9 +32,9 @@ namespace sb::di::details::core containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; - [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance &instance) const; + [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance *instance) const; - [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance &instance) const; + [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance *instance) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( const OneOrList &instances) const; diff --git a/Include/SevenBit/DI/Exceptions.hpp b/Include/SevenBit/DI/Exceptions.hpp index 95874bb..455ae46 100644 --- a/Include/SevenBit/DI/Exceptions.hpp +++ b/Include/SevenBit/DI/Exceptions.hpp @@ -57,6 +57,11 @@ namespace sb::di ServiceLifeTimeMismatchException(TypeId typeIndex, TypeId interface); }; + struct EXPORT ServiceAliasMismatchException : InjectorException + { + ServiceAliasMismatchException(TypeId typeIndex, TypeId interface, bool shoudBeAlias); + }; + struct EXPORT CircularDependencyException : InjectorException { explicit CircularDependencyException(TypeId typeIndex); diff --git a/Include/SevenBit/DI/Impl/Exceptions.hpp b/Include/SevenBit/DI/Impl/Exceptions.hpp index bf0f85e..5a2894d 100644 --- a/Include/SevenBit/DI/Impl/Exceptions.hpp +++ b/Include/SevenBit/DI/Impl/Exceptions.hpp @@ -51,6 +51,15 @@ namespace sb::di { } + INLINE ServiceAliasMismatchException::ServiceAliasMismatchException(const TypeId typeIndex, const TypeId interface, + const bool shoudBeAlias) + : InjectorException{std::string{"Service: '"} + typeIndex.name() + + (shoudBeAlias ? "' should be" : "' should not be") + + " alias as other services implementing this interface '" + interface.name() + + "' that are already registered."} + { + } + INLINE ServiceLifeTimeMismatchException::ServiceLifeTimeMismatchException(const TypeId typeIndex, const TypeId interface) : InjectorException{std::string{"Service: '"} + typeIndex.name() + diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index 48108ce..ad36b79 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -3,25 +3,34 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" namespace sb::di { - INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const ServiceLifeTime lifetime, + INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, + const std::optional lifeTime, IServiceFactory::Ptr implementationFactory) - : _serviceTypeId(serviceTypeId), _lifetime(lifetime), _implementationFactory(std::move(implementationFactory)) + : _serviceTypeId(serviceTypeId), _lifeTime(lifeTime), _implementationFactory(std::move(implementationFactory)) { details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); } - INLINE const ServiceLifeTime &ServiceDescriptor::getLifeTime() const { return _lifetime; } + INLINE ServiceLifeTime ServiceDescriptor::getLifeTime() const + { + if (_lifeTime) + { + return *_lifeTime; + } + throw InjectorException("descriptor does not contain lifetime it is considered as alias"); + } + + INLINE std::optional ServiceDescriptor::tryGetLifeTime() const { return _lifeTime; } INLINE TypeId ServiceDescriptor::getServiceTypeId() const { return _serviceTypeId; } INLINE TypeId ServiceDescriptor::getImplementationTypeId() const { - return _implementationFactory->getServiceTypeId(); + return getImplementationFactory().getServiceTypeId(); } INLINE const IServiceFactory &ServiceDescriptor::getImplementationFactory() const @@ -29,9 +38,11 @@ namespace sb::di return *_implementationFactory; } + INLINE bool ServiceDescriptor::isAlias() const { return !_lifeTime; } + INLINE bool ServiceDescriptor::operator==(const ServiceDescriptor &descriptor) const { - return _serviceTypeId == descriptor.getServiceTypeId() && _lifetime == descriptor.getLifeTime() && + return _serviceTypeId == descriptor.getServiceTypeId() && _lifeTime == descriptor._lifeTime && _implementationFactory.get() == &descriptor.getImplementationFactory(); } diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index f2bc536..1d3d561 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -5,7 +5,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" -#include "SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp" @@ -355,7 +354,7 @@ namespace sb::di details::utils::Assert::isNotSame(); details::utils::Assert::inheritance(); auto factory = std::make_unique>(); - return {typeid(TAlias), ServiceLifeTimes::Alias, std::move(factory)}; + return {typeid(TAlias), std::nullopt, std::move(factory)}; } private: diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index e46ae51..2369b3e 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "SevenBit/DI/LibraryConfig.hpp" @@ -13,7 +14,7 @@ namespace sb::di class EXPORT ServiceDescriptor { TypeId _serviceTypeId; - ServiceLifeTime _lifetime; + std::optional _lifeTime; IServiceFactory::SPtr _implementationFactory; public: @@ -24,7 +25,8 @@ namespace sb::di * @details implementationFactory cannot be null, otherwise constructor will throw exception * @throws sb::di::NullPointerException */ - ServiceDescriptor(TypeId serviceTypeId, ServiceLifeTime lifetime, IServiceFactory::Ptr implementationFactory); + ServiceDescriptor(TypeId serviceTypeId, std::optional lifeTime, + IServiceFactory::Ptr implementationFactory); ServiceDescriptor(const ServiceDescriptor &other) = default; ServiceDescriptor(ServiceDescriptor &&) = default; @@ -35,7 +37,9 @@ namespace sb::di /** * @brief Get the lifetime object */ - [[nodiscard]] const ServiceLifeTime &getLifeTime() const; + [[nodiscard]] ServiceLifeTime getLifeTime() const; + + [[nodiscard]] std::optional tryGetLifeTime() const; /** * @brief Get the service TypeId @@ -47,6 +51,7 @@ namespace sb::di */ [[nodiscard]] TypeId getImplementationTypeId() const; + [[nodiscard]] bool isAlias() const; /** * @brief Get the service implementation factory */ diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index b5f2582..0220b32 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -17,7 +17,6 @@ namespace sb::di Singleton, Scoped, Transient, - Alias, Count }; @@ -38,7 +37,6 @@ namespace sb::di * @brief creates transient service lifetime */ constexpr static ServiceLifeTime transient() { return ServiceLifeTime{Transient}; } - constexpr static ServiceLifeTime alias() { return ServiceLifeTime{Alias}; } /** * @brief Construct a new Service Life Time object with specified type @@ -54,7 +52,7 @@ namespace sb::di /** * @brief checks if lifetime is given type */ - [[nodiscard]] constexpr bool is(const Type type) const { return *this == type; } + [[nodiscard]] constexpr bool is(const Type type) const { return _type == type; } /** * @brief checks if lifetime is singleton */ @@ -67,10 +65,6 @@ namespace sb::di * @brief checks if lifetime is transient */ [[nodiscard]] constexpr bool isTransient() const { return is(Transient); } - /** - * @brief checks if lifetime is alias - */ - [[nodiscard]] constexpr bool isAlias() const { return is(Alias); } template [[nodiscard]] constexpr bool isAny(TServiceLifeTime... types) const { @@ -84,8 +78,5 @@ namespace sb::di constexpr bool operator!=(const ServiceLifeTime &lifeTime) const { return _type != lifeTime._type; } constexpr bool operator==(const ServiceLifeTime &lifeTime) const { return _type == lifeTime._type; } - - constexpr bool operator!=(const Type type) const { return _type != type; } - constexpr bool operator==(const Type type) const { return _type == type; } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceLifeTimes.hpp b/Include/SevenBit/DI/ServiceLifeTimes.hpp index aa79616..41e03dd 100644 --- a/Include/SevenBit/DI/ServiceLifeTimes.hpp +++ b/Include/SevenBit/DI/ServiceLifeTimes.hpp @@ -11,6 +11,5 @@ namespace sb::di constexpr static ServiceLifeTime Singleton = ServiceLifeTime::singleton(); constexpr static ServiceLifeTime Scoped = ServiceLifeTime::scoped(); constexpr static ServiceLifeTime Transient = ServiceLifeTime::transient(); - constexpr static ServiceLifeTime Alias = ServiceLifeTime::alias(); }; } // namespace sb::di From 1e7a2321389af169fef9ac4b747fbd759f7d7757 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 28 Jan 2024 17:14:20 +0100 Subject: [PATCH 22/45] improve alias code --- .../Core/Impl/ServiceInstanceCreator.hpp | 1 - .../Core/Impl/ServiceInstanceProvider.hpp | 2 +- .../Core/Impl/ServiceInstancesResolver.hpp | 39 +++++++++++-------- .../Details/Core/ServiceInstancesResolver.hpp | 22 +++-------- .../DI/Details/Services/AliasService.hpp | 2 +- .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 2 +- Include/SevenBit/DI/ServiceDescriptor.hpp | 3 +- 7 files changed, 32 insertions(+), 39 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index a07a606..4577c89 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -28,7 +28,6 @@ namespace sb::di::details::core TypeId serviceTypeId) { utils::Require::notNull(instance); - // auto _ = _guard(serviceTypeId); return std::make_unique(instance->get(), serviceTypeId); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 11bf8cb..39679dc 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -140,7 +140,7 @@ namespace sb::di::details::core { if (const auto original = tryGetInstance(descriptors.last().getImplementationTypeId())) { - return makeResolver(descriptors).createOneAlias(original); + return makeResolver(descriptors).createOneAlias(*original); } return std::nullopt; } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 732113c..a1b0142 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -6,7 +6,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" -#include "SevenBit/DI/Details/Services/AliasService.hpp" namespace sb::di::details::core { @@ -55,42 +54,42 @@ namespace sb::di::details::core return createRestInstances(instances, true); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance *instance) const + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance &original) const { - return _creator.createInstanceAlias(instance, _descriptors.last().getImplementationTypeId()); + return createAlias(&original); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAlias( - const IServiceInstance *instance) const + const IServiceInstance &original) const { - return containers::ServiceInstanceList{createAlias(instance)}; + return containers::ServiceInstanceList{createAlias(&original)}; } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( - const OneOrList &instances) const + const OneOrList &originals) const { - containers::ServiceInstanceList aliases{createAlias(instances.last().get())}; - return std::move(createRestAliases(instances, aliases)); + containers::ServiceInstanceList aliases{createAlias(originals.last().get())}; + return std::move(createRestAliases(originals, aliases)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( - const OneOrList &instances, containers::ServiceInstanceList &toFill) const + const OneOrList &originals, containers::ServiceInstanceList &instances) const { - if (instances.size() > 1) + if (originals.size() > 1) { - auto &list = instances.getAsList(); - toFill.reserve(list.size()); + auto &list = originals.getAsList(); + instances.reserve(list.size()); auto realFirst = createAlias(list.front().get()); const auto end = --list.end(); for (auto it = ++list.begin(); it != end; ++it) // skip first and last { - toFill.add(createAlias(it->get())); + instances.add(createAlias(it->get())); } - toFill.add(std::move(realFirst)); - toFill.first().swap(toFill.last()); + instances.add(std::move(realFirst)); + instances.first().swap(instances.last()); } - toFill.seal(); - return toFill; + instances.seal(); + return instances; } INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const @@ -132,4 +131,10 @@ namespace sb::di::details::core instances.seal(); return instances; } + + INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance *original) const + { + return _creator.createInstanceAlias(original, _descriptors.last().getImplementationTypeId()); + } + } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index 91aed6b..bbd5c10 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -17,40 +17,30 @@ namespace sb::di::details::core ServiceInstancesResolver(ServiceInstanceCreator &creator, const containers::ServiceDescriptorList &descriptors); [[nodiscard]] IServiceInstance::Ptr createInstance() const; - [[nodiscard]] containers::ServiceInstanceList createOneInstance() const; - [[nodiscard]] containers::ServiceInstanceList createAllInstances() const; - containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances) const; [[nodiscard]] IServiceInstance::Ptr createInstanceInPlace() const; - [[nodiscard]] containers::ServiceInstanceList createOneInstanceInPlace() const; - [[nodiscard]] containers::ServiceInstanceList createAllInstancesInPlace() const; - containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; - [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance *instance) const; - - [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance *instance) const; - + [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance &original) const; + [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance &original) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( - const OneOrList &instances) const; - + const OneOrList &originals) const; [[nodiscard]] containers::ServiceInstanceList &createRestAliases( - const OneOrList &instances, containers::ServiceInstanceList &toFill) const; + const OneOrList &originals, containers::ServiceInstanceList &instances) const; private: [[nodiscard]] IServiceInstance::Ptr createInstance(bool inPlaceRequest) const; - [[nodiscard]] containers::ServiceInstanceList createOneInstance(bool inPlaceRequest) const; - [[nodiscard]] containers::ServiceInstanceList createAllInstances(bool inPlaceRequest) const; - containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, bool inPlaceRequest) const; + + [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance *original) const; }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Services/AliasService.hpp b/Include/SevenBit/DI/Details/Services/AliasService.hpp index c9e1a08..f108cfb 100644 --- a/Include/SevenBit/DI/Details/Services/AliasService.hpp +++ b/Include/SevenBit/DI/Details/Services/AliasService.hpp @@ -12,7 +12,7 @@ namespace sb::di::details::services class AliasService final : public IServiceInstance { void *_service = nullptr; - const TypeId _serviceTypeId; + TypeId _serviceTypeId; public: using Ptr = std::unique_ptr; diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index ad36b79..580be08 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -42,7 +42,7 @@ namespace sb::di INLINE bool ServiceDescriptor::operator==(const ServiceDescriptor &descriptor) const { - return _serviceTypeId == descriptor.getServiceTypeId() && _lifeTime == descriptor._lifeTime && + return _serviceTypeId == descriptor.getServiceTypeId() && _lifeTime == descriptor.tryGetLifeTime() && _implementationFactory.get() == &descriptor.getImplementationFactory(); } diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index 2369b3e..02f21d5 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -1,7 +1,6 @@ #pragma once -#include -#include +#include #include "SevenBit/DI/LibraryConfig.hpp" From 6f4ade2c66726ef2bfc28b7cbc6ccf79e4858a95 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 28 Jan 2024 20:39:37 +0100 Subject: [PATCH 23/45] improve alias code --- .../Core/Impl/ServiceInstanceProvider.hpp | 59 ++++++------------- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 2 +- .../Details/Core/ServiceInstanceProvider.hpp | 16 ++--- .../Core/ServiceInstanceProviderRoot.hpp | 1 - .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 25 +++----- Include/SevenBit/DI/ServiceDescriber.hpp | 2 +- Include/SevenBit/DI/ServiceDescriptor.hpp | 9 ++- Include/SevenBit/DI/ServiceLifeTime.hpp | 10 ---- 8 files changed, 40 insertions(+), 84 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 39679dc..abbcc9c 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -50,8 +50,8 @@ namespace sb::di::details::core auto instances = findRegisteredInstances(serviceTypeId); if (!instances) { - const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? tryRegister(*descriptors, tryCreate(*descriptors)) : nullptr; + const auto descriptors = findDescriptors(serviceTypeId, false); + instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreate(*descriptors)) : nullptr; } return instances ? instances->last().get() : nullptr; } @@ -61,13 +61,13 @@ namespace sb::di::details::core auto instances = findRegisteredInstances(serviceTypeId); if (!instances) { - const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? tryRegister(*descriptors, tryCreateAll(*descriptors)) : nullptr; + const auto descriptors = findDescriptors(serviceTypeId, false); + instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreateAll(*descriptors)) : nullptr; } else if (!instances->isSealed()) { - const auto descriptors = findNonTransientDescriptors(serviceTypeId); - instances = descriptors ? createRest(*descriptors, *instances) : nullptr; + const auto descriptors = findDescriptors(serviceTypeId, false); + instances = descriptors ? createRestAndGet(*descriptors, *instances) : nullptr; } return instances ? &instances->getInnerList() : nullptr; } @@ -84,7 +84,7 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { - if (const auto descriptors = findTransientDescriptors(serviceTypeId)) + if (const auto descriptors = findDescriptors(serviceTypeId, true)) { if (descriptors->isAlias()) { @@ -98,14 +98,13 @@ namespace sb::di::details::core INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { - if (const auto descriptors = findTransientDescriptors(serviceTypeId)) + if (const auto descriptors = findDescriptors(serviceTypeId, true)) { if (descriptors->isAlias()) { return tryCreateInstances(descriptors->last().getImplementationTypeId()); } - auto instances = makeResolver(*descriptors).createAllInstances(); - return std::move(instances.getInnerList()); + return std::move(makeResolver(*descriptors).createAllInstances().getInnerList()); } return std::nullopt; } @@ -123,8 +122,8 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { - if (const auto descriptors = findTransientDescriptors(serviceTypeId); - descriptors && descriptors->last().getImplementationTypeId() == serviceTypeId) + if (const auto descriptors = findDescriptors(serviceTypeId, true); + descriptors && !descriptors->isAlias() && descriptors->last().getImplementationTypeId() == serviceTypeId) { return makeResolver(*descriptors).createInstanceInPlace(); } @@ -161,7 +160,7 @@ namespace sb::di::details::core return makeResolver(descriptors).createAllInstancesInPlace(); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRest( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRestAndGet( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { if (descriptors.isAlias()) @@ -175,7 +174,7 @@ namespace sb::di::details::core return &makeResolver(descriptors).createRestInstancesInPlace(instances); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegister( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegisterAndGet( const containers::ServiceDescriptorList &descriptors, std::optional instances) { return instances ? &getInstancesMap(getLifeTime(descriptors)) @@ -207,12 +206,13 @@ namespace sb::di::details::core return lifeTime.isSingleton() ? _root.getSingletons() : _scoped; } - INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findTransientDescriptors( - const TypeId serviceTypeId) const + INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors(const TypeId serviceTypeId, + const bool transient) const { - if (const auto descriptors = findDescriptors(serviceTypeId)) + if (const auto descriptors = _root.getDescriptorsMap().findDescriptors(serviceTypeId)) { - if (descriptors->isAlias() || descriptors->getLifeTime().isTransient()) + if (const auto isTransient = descriptors->getLifeTime().isTransient(); + descriptors->isAlias() || (transient ? isTransient : !isTransient)) { return descriptors; } @@ -220,31 +220,10 @@ namespace sb::di::details::core return nullptr; } - INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findNonTransientDescriptors( - const TypeId serviceTypeId) const - { - if (const auto descriptors = findDescriptors(serviceTypeId)) - { - if (descriptors->isAlias() || - descriptors->getLifeTime().isAny(ServiceLifeTimes::Singleton, ServiceLifeTimes::Scoped)) - { - return descriptors; - } - } - return nullptr; - } - - INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors( - const TypeId serviceTypeId) const - { - return _root.getDescriptorsMap().findDescriptors(serviceTypeId); - } - INLINE ServiceInstancesResolver ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { - auto &creator = descriptors.isAlias() || descriptors.getLifeTime().isSingleton() ? _root._instanceCreator - : _instanceCreator; + auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; return ServiceInstancesResolver{creator, descriptors}; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index cb7ba01..d2756cc 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -28,7 +28,7 @@ namespace sb::di::details::core { if (!descriptors.isAlias() && descriptors.getLifeTime().isSingleton()) { - tryRegister(descriptors, tryCreateAll(descriptors)); + tryRegisterAndGet(descriptors, tryCreateAll(descriptors)); } } } diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index fcea9b8..25d8600 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -24,9 +24,6 @@ namespace sb::di::details::core ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; - using InstanceResult = std::pair; - using InstancesResult = std::pair; - public: using Ptr = std::unique_ptr; @@ -61,21 +58,20 @@ namespace sb::di::details::core std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); std::optional tryCreateAll( const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList *createRest(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); + containers::ServiceInstanceList *createRestAndGet(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances); containers::ServiceInstancesMap &getInstancesMap(ServiceLifeTime lifeTime); containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); - containers::ServiceInstanceList *tryRegister(const containers::ServiceDescriptorList &descriptors, - std::optional instances); + containers::ServiceInstanceList *tryRegisterAndGet(const containers::ServiceDescriptorList &descriptors, + std::optional instances); [[nodiscard]] ServiceLifeTime getLifeTime(const containers::ServiceDescriptorList &descriptors) const; - [[nodiscard]] const containers::ServiceDescriptorList *findTransientDescriptors(TypeId serviceTypeId) const; - [[nodiscard]] const containers::ServiceDescriptorList *findNonTransientDescriptors(TypeId serviceTypeId) const; - [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId) const; + [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId, + bool transient) const; ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); }; diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index d158037..64b1d1f 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -8,7 +8,6 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" -#include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index 580be08..75ebf07 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -7,24 +7,16 @@ namespace sb::di { - INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, - const std::optional lifeTime, - IServiceFactory::Ptr implementationFactory) - : _serviceTypeId(serviceTypeId), _lifeTime(lifeTime), _implementationFactory(std::move(implementationFactory)) - { - details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); - } + INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const ServiceLifeTime lifeTime, + IServiceFactory::Ptr implementationFactory, bool isAlias) + : _serviceTypeId(serviceTypeId), _lifeTime(lifeTime), _isAlias(isAlias), + _implementationFactory(std::move(implementationFactory)) - INLINE ServiceLifeTime ServiceDescriptor::getLifeTime() const { - if (_lifeTime) - { - return *_lifeTime; - } - throw InjectorException("descriptor does not contain lifetime it is considered as alias"); + details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); } - INLINE std::optional ServiceDescriptor::tryGetLifeTime() const { return _lifeTime; } + INLINE ServiceLifeTime ServiceDescriptor::getLifeTime() const { return _lifeTime; } INLINE TypeId ServiceDescriptor::getServiceTypeId() const { return _serviceTypeId; } @@ -38,11 +30,12 @@ namespace sb::di return *_implementationFactory; } - INLINE bool ServiceDescriptor::isAlias() const { return !_lifeTime; } + INLINE bool ServiceDescriptor::isAlias() const { return _isAlias; } INLINE bool ServiceDescriptor::operator==(const ServiceDescriptor &descriptor) const { - return _serviceTypeId == descriptor.getServiceTypeId() && _lifeTime == descriptor.tryGetLifeTime() && + return _isAlias == descriptor.isAlias() && _serviceTypeId == descriptor.getServiceTypeId() && + _lifeTime == descriptor.getLifeTime() && _implementationFactory.get() == &descriptor.getImplementationFactory(); } diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 1d3d561..84ead1d 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -354,7 +354,7 @@ namespace sb::di details::utils::Assert::isNotSame(); details::utils::Assert::inheritance(); auto factory = std::make_unique>(); - return {typeid(TAlias), std::nullopt, std::move(factory)}; + return {typeid(TAlias), ServiceLifeTimes::Scoped, std::move(factory), true}; } private: diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index 02f21d5..b4ffe3c 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -13,7 +13,8 @@ namespace sb::di class EXPORT ServiceDescriptor { TypeId _serviceTypeId; - std::optional _lifeTime; + ServiceLifeTime _lifeTime; + bool _isAlias; IServiceFactory::SPtr _implementationFactory; public: @@ -24,8 +25,8 @@ namespace sb::di * @details implementationFactory cannot be null, otherwise constructor will throw exception * @throws sb::di::NullPointerException */ - ServiceDescriptor(TypeId serviceTypeId, std::optional lifeTime, - IServiceFactory::Ptr implementationFactory); + ServiceDescriptor(TypeId serviceTypeId, ServiceLifeTime lifeTime, IServiceFactory::Ptr implementationFactory, + bool isAlias = false); ServiceDescriptor(const ServiceDescriptor &other) = default; ServiceDescriptor(ServiceDescriptor &&) = default; @@ -38,8 +39,6 @@ namespace sb::di */ [[nodiscard]] ServiceLifeTime getLifeTime() const; - [[nodiscard]] std::optional tryGetLifeTime() const; - /** * @brief Get the service TypeId */ diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index 0220b32..de5d102 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -66,16 +66,6 @@ namespace sb::di */ [[nodiscard]] constexpr bool isTransient() const { return is(Transient); } - template [[nodiscard]] constexpr bool isAny(TServiceLifeTime... types) const - { - return ((*this == types) || ...); - } - - template [[nodiscard]] constexpr bool isNot(TServiceLifeTime... types) const - { - return ((*this != types) && ...); - } - constexpr bool operator!=(const ServiceLifeTime &lifeTime) const { return _type != lifeTime._type; } constexpr bool operator==(const ServiceLifeTime &lifeTime) const { return _type == lifeTime._type; } }; From c1b99baac4db469ef92cac1b91529236f403f2ba Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 28 Jan 2024 23:00:51 +0100 Subject: [PATCH 24/45] rearrange code --- .../Containers/ServiceDescriptorList.hpp | 6 ++ .../Containers/ServiceInstanceList.hpp | 3 + .../Core/Impl/ServiceInstanceCreator.hpp | 4 +- .../Core/Impl/ServiceInstanceProvider.hpp | 85 +++++++++---------- .../Core/Impl/ServiceInstancesResolver.hpp | 2 +- .../Details/Core/ServiceInstanceCreator.hpp | 2 +- .../Details/Core/ServiceInstanceProvider.hpp | 26 +++--- 7 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp index b820657..b46c562 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp @@ -18,6 +18,12 @@ namespace sb::di::details::containers public: explicit ServiceDescriptorList(ServiceDescriptor &&descriptor); + ServiceDescriptorList(const ServiceDescriptorList &) = delete; + ServiceDescriptorList(ServiceDescriptorList &&) = default; + + ServiceDescriptorList &operator=(const ServiceDescriptorList &) = delete; + ServiceDescriptorList &operator=(ServiceDescriptorList &&) = default; + void add(ServiceDescriptor &&descriptor); [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index 8a2ce4e..c8b0e86 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -26,6 +26,9 @@ namespace sb::di::details::containers void add(IServiceInstance::Ptr &&service); + [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } + [[nodiscard]] auto end() const { return _oneOrList.getAsList().end(); } + OneOrList &getInnerList(); [[nodiscard]] const OneOrList &getInnerList() const; diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 4577c89..55604b6 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -24,8 +24,8 @@ namespace sb::di::details::core return utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); } - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(const IServiceInstance *instance, - TypeId serviceTypeId) + INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(TypeId serviceTypeId, + const IServiceInstance *instance) { utils::Require::notNull(instance); return std::make_unique(instance->get(), serviceTypeId); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index abbcc9c..e63a95f 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -30,6 +30,8 @@ namespace sb::di::details::core _scoped.insert(external->getTypeId(), std::move(external)).seal(); } + INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } + INLINE IServiceInstanceProvider::Ptr ServiceInstanceProvider::createScope() const { return std::make_unique(_root, _options); @@ -132,6 +134,43 @@ namespace sb::di::details::core INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::findRegisteredInstances(const TypeId serviceTypeId) + { + const auto singletons = _root.getSingletons().findServices(serviceTypeId); + return singletons ? singletons : _scoped.findServices(serviceTypeId); + } + + INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors(const TypeId serviceTypeId, + const bool transient) const + { + if (const auto descriptors = _root.getDescriptorsMap().findDescriptors(serviceTypeId)) + { + if (const auto isTransient = descriptors->getLifeTime().isTransient(); + descriptors->isAlias() || (transient ? isTransient : !isTransient)) + { + return descriptors; + } + } + return nullptr; + } + + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegisterAndGet( + const containers::ServiceDescriptorList &descriptors, std::optional instances) + { + if (!instances) + { + return nullptr; + } + auto lifeTime = descriptors.getLifeTime(); + if (descriptors.isAlias()) + { + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; + } + auto &instancesMap = lifeTime.isSingleton() ? _root.getSingletons() : _scoped; + return &instancesMap.insert(descriptors.getServiceTypeId(), std::move(*instances)); + } + INLINE std::optional ServiceInstanceProvider::tryCreate( const containers::ServiceDescriptorList &descriptors) { @@ -174,52 +213,6 @@ namespace sb::di::details::core return &makeResolver(descriptors).createRestInstancesInPlace(instances); } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegisterAndGet( - const containers::ServiceDescriptorList &descriptors, std::optional instances) - { - return instances ? &getInstancesMap(getLifeTime(descriptors)) - .insert(descriptors.getServiceTypeId(), std::move(*instances)) - : nullptr; - } - - INLINE ServiceLifeTime - ServiceInstanceProvider::getLifeTime(const containers::ServiceDescriptorList &descriptors) const - { - if (descriptors.isAlias()) - { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); - return _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; - } - return descriptors.getLifeTime(); - } - - INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } - - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::findRegisteredInstances(const TypeId serviceTypeId) - { - const auto singletons = _root.getSingletons().findServices(serviceTypeId); - return singletons ? singletons : _scoped.findServices(serviceTypeId); - } - - INLINE containers::ServiceInstancesMap &ServiceInstanceProvider::getInstancesMap(const ServiceLifeTime lifeTime) - { - return lifeTime.isSingleton() ? _root.getSingletons() : _scoped; - } - - INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors(const TypeId serviceTypeId, - const bool transient) const - { - if (const auto descriptors = _root.getDescriptorsMap().findDescriptors(serviceTypeId)) - { - if (const auto isTransient = descriptors->getLifeTime().isTransient(); - descriptors->isAlias() || (transient ? isTransient : !isTransient)) - { - return descriptors; - } - } - return nullptr; - } - INLINE ServiceInstancesResolver ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index a1b0142..a139544 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -134,7 +134,7 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance *original) const { - return _creator.createInstanceAlias(original, _descriptors.last().getImplementationTypeId()); + return _creator.createInstanceAlias(_descriptors.last().getImplementationTypeId(), original); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index c2a36f0..f8ff995 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -17,7 +17,7 @@ namespace sb::di::details::core IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); - IServiceInstance::Ptr createInstanceAlias(const IServiceInstance *instance, TypeId serviceTypeId); + IServiceInstance::Ptr createInstanceAlias(TypeId serviceTypeId, const IServiceInstance *instance); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 25d8600..5d91248 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -24,6 +24,8 @@ namespace sb::di::details::core ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; + using ServiceDescriptorList = containers::ServiceDescriptorList; + public: using Ptr = std::unique_ptr; @@ -37,6 +39,8 @@ namespace sb::di::details::core void init(ServiceProvider &serviceProvider) override; + [[nodiscard]] const ServiceProviderOptions &getOptions() const override; + [[nodiscard]] IServiceInstanceProvider::Ptr createScope() const override; const IServiceInstance &getInstance(TypeId serviceTypeId) override; @@ -52,26 +56,20 @@ namespace sb::di::details::core void clear(); - [[nodiscard]] const ServiceProviderOptions &getOptions() const override; - protected: - std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); - std::optional tryCreateAll( - const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList *createRestAndGet(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); - - containers::ServiceInstancesMap &getInstancesMap(ServiceLifeTime lifeTime); - containers::ServiceInstanceList *findRegisteredInstances(TypeId serviceTypeId); + [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId, + bool transient) const; + containers::ServiceInstanceList *tryRegisterAndGet(const containers::ServiceDescriptorList &descriptors, std::optional instances); - [[nodiscard]] ServiceLifeTime getLifeTime(const containers::ServiceDescriptorList &descriptors) const; - - [[nodiscard]] const containers::ServiceDescriptorList *findDescriptors(TypeId serviceTypeId, - bool transient) const; + std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); + std::optional tryCreateAll( + const containers::ServiceDescriptorList &descriptors); + containers::ServiceInstanceList *createRestAndGet(const containers::ServiceDescriptorList &descriptors, + containers::ServiceInstanceList &instances); ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); }; From d54f51f8ec2397bf413d8c806b5c93d68281f906 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 29 Jan 2024 20:06:00 +0100 Subject: [PATCH 25/45] update tests --- .../Containers/Impl/ServiceDescriptorsMap.hpp | 41 +++--- .../Containers/ServiceDescriptorsMap.hpp | 7 +- .../Core/Impl/ServiceInstanceCreator.hpp | 6 +- .../Factories/ExternalServiceFcnFactory.hpp | 42 ------- .../Details/Factories/ServiceFcnFactory.hpp | 25 ++-- .../Factories/UniquePtrServiceFcnFactory.hpp | 43 ------- .../DI/Details/Services/ExternalService.hpp | 2 - Include/SevenBit/DI/Details/Utils/Assert.hpp | 21 +++- Include/SevenBit/DI/Details/Utils/Check.hpp | 10 +- .../Utils/{IsPtr.hpp => Inheritance.hpp} | 6 +- .../SevenBit/DI/Details/Utils/RemovePtr.hpp | 13 -- Include/SevenBit/DI/ServiceDescriber.hpp | 58 ++------- Include/SevenBit/DI/ServiceDescriptor.hpp | 6 +- .../Containers/ServiceDescriptorListTest.cpp | 37 ++++++ .../Containers/ServiceInstanceListTest.cpp | 1 - .../Unit/Core/ServiceInstanceCreatorTest.cpp | 117 ++++++++++++++++++ .../Unit/Core/ServiceInstanceProviderTest.cpp | 26 ++-- .../Unit/Core/ServiceInstanceResolverTest.cpp | 117 ++++++++++++++++++ .../Unit/Factories/ServiceFcnFactoryTest.cpp | 26 ++-- .../Unit/Factories/VoidServiceFactoryTest.cpp | 44 +++++++ ...oker.cpp => ServiceFactoryInvokerTest.cpp} | 8 +- Tests/Unit/ServiceCollectionTest.cpp | 28 +++-- Tests/Unit/ServiceDescriberTest.cpp | 41 +++++- Tests/Unit/ServiceDescriptorTest.cpp | 15 +++ Tests/Unit/ServiceLifeTimeTest.cpp | 23 +++- Tests/Unit/Services/AliasServiceTest.cpp | 80 ++++++++++++ Tests/Unit/Services/ExternalServiceTest.cpp | 17 --- Tests/Unit/Utils/CheckTest.cpp | 31 +++++ Tests/Unit/Utils/InheritanceTest.cpp | 40 ++++++ ...laceObject.cpp => IsInPlaceObjectTest.cpp} | 0 .../{IsUniquePtr.cpp => IsUniquePtrTest.cpp} | 0 Tests/Unit/Utils/RemoveUniquePtrTest.cpp | 32 +++++ Tests/Unit/Utils/RequireTest.cpp | 20 ++- 33 files changed, 711 insertions(+), 272 deletions(-) delete mode 100644 Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp delete mode 100644 Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp rename Include/SevenBit/DI/Details/Utils/{IsPtr.hpp => Inheritance.hpp} (51%) delete mode 100644 Include/SevenBit/DI/Details/Utils/RemovePtr.hpp create mode 100644 Tests/Unit/Core/ServiceInstanceCreatorTest.cpp create mode 100644 Tests/Unit/Core/ServiceInstanceResolverTest.cpp create mode 100644 Tests/Unit/Factories/VoidServiceFactoryTest.cpp rename Tests/Unit/Helpers/{ServiceFactoryInvoker.cpp => ServiceFactoryInvokerTest.cpp} (82%) create mode 100644 Tests/Unit/Services/AliasServiceTest.cpp create mode 100644 Tests/Unit/Utils/InheritanceTest.cpp rename Tests/Unit/Utils/{IsInPlaceObject.cpp => IsInPlaceObjectTest.cpp} (100%) rename Tests/Unit/Utils/{IsUniquePtr.cpp => IsUniquePtrTest.cpp} (100%) create mode 100644 Tests/Unit/Utils/RemoveUniquePtrTest.cpp diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp index 651e512..b14b332 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp @@ -7,26 +7,17 @@ namespace sb::di::details::containers { INLINE ServiceDescriptorsMap::ServiceDescriptorsMap(const bool checkDescriptorUniqueness) - : _checkDescriptorUniqueness(checkDescriptorUniqueness) { + _registeredServicesCheck = checkDescriptorUniqueness ? std::make_unique>() : nullptr; } INLINE void ServiceDescriptorsMap::add(ServiceDescriptor descriptor) { - if (_checkDescriptorUniqueness) - { - const auto implementationTypeId = descriptor.getImplementationTypeId(); - checkIfAlreadyRegistered(implementationTypeId); - addDescriptor(std::move(descriptor)); - registerService(implementationTypeId); - } - else - { - addDescriptor(std::move(descriptor)); - } + return _registeredServicesCheck ? addDescriptorWithCheck(std::move(descriptor)) + : addDescriptor(std::move(descriptor)); } - INLINE void ServiceDescriptorsMap::seal() { _registeredServices.clear(); } + INLINE void ServiceDescriptorsMap::seal() { _registeredServicesCheck.reset(); } INLINE const ServiceDescriptorList *ServiceDescriptorsMap::findDescriptors(const TypeId typeId) const { @@ -37,6 +28,17 @@ namespace sb::di::details::containers return nullptr; } + INLINE void ServiceDescriptorsMap::addDescriptorWithCheck(ServiceDescriptor &&descriptor) + { + const auto implementationTypeId = descriptor.getImplementationTypeId(); + if (_registeredServicesCheck->count(implementationTypeId)) + { + throw ServiceAlreadyRegisteredException{implementationTypeId}; + } + addDescriptor(std::move(descriptor)); + _registeredServicesCheck->insert(implementationTypeId); + } + INLINE void ServiceDescriptorsMap::addDescriptor(ServiceDescriptor &&descriptor) { auto serviceTypeId = descriptor.getServiceTypeId(); @@ -50,17 +52,4 @@ namespace sb::di::details::containers } } - INLINE void ServiceDescriptorsMap::checkIfAlreadyRegistered(const TypeId implementationTypeId) - { - if (_registeredServices.count(implementationTypeId)) - { - throw ServiceAlreadyRegisteredException{implementationTypeId}; - } - } - - INLINE void ServiceDescriptorsMap::registerService(const TypeId implementationTypeId) - { - _registeredServices.insert(implementationTypeId); - } - } // namespace sb::di::details::containers diff --git a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp index 0f4d01c..3f755ac 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp @@ -15,8 +15,7 @@ namespace sb::di::details::containers class EXPORT ServiceDescriptorsMap { std::unordered_map _serviceCreatorsMap; - std::unordered_set _registeredServices; - const bool _checkDescriptorUniqueness = false; + std::unique_ptr> _registeredServicesCheck; public: using Ptr = std::unique_ptr; @@ -48,10 +47,8 @@ namespace sb::di::details::containers [[nodiscard]] const ServiceDescriptorList *findDescriptors(TypeId typeId) const; private: + void addDescriptorWithCheck(ServiceDescriptor &&descriptor); void addDescriptor(ServiceDescriptor &&descriptor); - - void checkIfAlreadyRegistered(TypeId implementationTypeId); - void registerService(TypeId implementationTypeId); }; } // namespace sb::di::details::containers diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 55604b6..5dd0288 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -1,12 +1,12 @@ #pragma once #include -#include #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" -#include +#include "SevenBit/DI/Details/Services/AliasService.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" namespace sb::di::details::core { @@ -27,7 +27,7 @@ namespace sb::di::details::core INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(TypeId serviceTypeId, const IServiceInstance *instance) { - utils::Require::notNull(instance); + utils::Require::validInstance(instance); return std::make_unique(instance->get(), serviceTypeId); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp deleted file mode 100644 index 48f9158..0000000 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFcnFactory.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" -#include "SevenBit/DI/Details/Services/ExternalService.hpp" -#include "SevenBit/DI/Details/Utils/IsPtr.hpp" -#include "SevenBit/DI/Details/Utils/RemovePtr.hpp" -#include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/TypeId.hpp" - -namespace sb::di::details::factories -{ - template class ExternalServiceFcnFactory final : public IServiceFactory - { - using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; - using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; - using ServiceType = utils::RemovePtrT; - - mutable FactoryFcn _factoryFunction; - - public: - explicit ExternalServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} - { - static_assert(utils::IsPtrV || utils::notSupportedType, - "Service factory return type must be pointer"); - } - - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } - - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override - { - ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - return std::make_unique>(invoker.invoke()); - } - }; -} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index f35cb3d..c4ebf16 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -8,6 +8,8 @@ #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" +#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" +#include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" @@ -17,16 +19,18 @@ namespace sb::di::details::factories template class ServiceFcnFactory final : public IServiceFactory { using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; + using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; mutable FactoryFcn _factoryFunction; public: - using ServiceType = typename ServiceFactoryInvoker::ReturnType; + using ServiceType = utils::RemoveUniquePtrT; explicit ServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} { - static_assert(utils::IsInPlaceObjectConstructableV || utils::notSupportedType, - "Service factory return type must be copyable or movable"); + static_assert(utils::IsInPlaceObjectConstructableV || utils::IsUniquePtrV || + utils::notSupportedType, + "Service factory return type must be std::unique_ptr or copyable/movable object"); } [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } @@ -34,12 +38,19 @@ namespace sb::di::details::factories IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - if (inPlaceRequest) + if constexpr (utils::IsUniquePtrV) { - return std::make_unique>(invoker.invoke()); + return std::make_unique>(invoker.invoke()); + } + else + { + if (inPlaceRequest) + { + return std::make_unique>(invoker.invoke()); + } + auto servicePtr = std::make_unique(invoker.invoke()); + return std::make_unique>(std::move(servicePtr)); } - auto servicePtr = std::make_unique(invoker.invoke()); - return std::make_unique>(std::move(servicePtr)); } }; } // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp deleted file mode 100644 index da3f264..0000000 --- a/Include/SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" -#include "SevenBit/DI/Details/Services/UniquePtrService.hpp" -#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" -#include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" -#include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/TypeId.hpp" - -namespace sb::di::details::factories -{ - template class UniquePtrServiceFcnFactory final : public IServiceFactory - { - using ServiceFactoryInvoker = helpers::ServiceFactoryInvoker; - using FactoryReturnType = typename ServiceFactoryInvoker::ReturnType; - - mutable FactoryFcn _factoryFunction; - - public: - using ServiceType = utils::RemoveUniquePtrT; - - explicit UniquePtrServiceFcnFactory(FactoryFcn &&factoryFunction) : _factoryFunction{std::move(factoryFunction)} - { - static_assert(utils::IsUniquePtrV || utils::notSupportedType, - "Service factory return type must be std::unique_ptr"); - } - - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } - - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override - { - ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; - return std::make_unique>(invoker.invoke()); - } - }; -} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Details/Services/ExternalService.hpp b/Include/SevenBit/DI/Details/Services/ExternalService.hpp index 93b02ea..f97a8d4 100644 --- a/Include/SevenBit/DI/Details/Services/ExternalService.hpp +++ b/Include/SevenBit/DI/Details/Services/ExternalService.hpp @@ -24,8 +24,6 @@ namespace sb::di::details::services ExternalService &operator=(const ExternalService &) = default; ExternalService &operator=(ExternalService &&) = default; - void update(T *service) { _service = service; } - [[nodiscard]] void *get() const override { return _service; } void *getForMoveOut() override diff --git a/Include/SevenBit/DI/Details/Utils/Assert.hpp b/Include/SevenBit/DI/Details/Utils/Assert.hpp index feaaaf1..bfd7b7e 100644 --- a/Include/SevenBit/DI/Details/Utils/Assert.hpp +++ b/Include/SevenBit/DI/Details/Utils/Assert.hpp @@ -4,19 +4,32 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/Inheritance.hpp" + namespace sb::di::details::utils { struct EXPORT Assert { template static void inheritance() { - static_assert(std::is_same_v || std::is_base_of_v, - "Type TImplementation must inherit from TService"); + static_assert(InheritanceV, + "Service implementation type: TImplementation must inherit from TService"); + } + + template static void factoryInheritance() + { + static_assert(InheritanceV, + "Service factory return type: TFactoryReturnType must inherit from TService"); + } + + template static void aliasInheritance() + { + static_assert(InheritanceV, "TService must inherit from alias type: TAlias"); } - template static void isNotSame() + template static void aliasNotSame() { - static_assert(!std::is_same_v, "Type TAlias cannot be same as TService"); + static_assert(!std::is_same_v, "Alias type: TAlias cannot be same as TService"); } }; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 6b72192..98ceb8d 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -9,11 +9,15 @@ namespace sb::di::details::utils { struct EXPORT Check { - template static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } + template constexpr static bool isSame() { return std::is_same_v; } - template static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } + template constexpr static bool inheritance() {} - template static bool notNull(const T *ptr) { return ptr != nullptr; } + template constexpr static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } + + template constexpr static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } + + template constexpr static bool notNull(const T *ptr) { return ptr != nullptr; } template constexpr static bool enumValidity(TEnum value) { diff --git a/Include/SevenBit/DI/Details/Utils/IsPtr.hpp b/Include/SevenBit/DI/Details/Utils/Inheritance.hpp similarity index 51% rename from Include/SevenBit/DI/Details/Utils/IsPtr.hpp rename to Include/SevenBit/DI/Details/Utils/Inheritance.hpp index 8dbcb34..297f346 100644 --- a/Include/SevenBit/DI/Details/Utils/IsPtr.hpp +++ b/Include/SevenBit/DI/Details/Utils/Inheritance.hpp @@ -1,14 +1,12 @@ #pragma once -#include #include #include "SevenBit/DI/LibraryConfig.hpp" namespace sb::di::details::utils { - template using IsPtr = std::is_pointer; - - template inline constexpr bool IsPtrV = IsPtr::value; + template + inline constexpr bool InheritanceV = std::is_same_v || std::is_base_of_v; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp b/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp deleted file mode 100644 index 7633c7e..0000000 --- a/Include/SevenBit/DI/Details/Utils/RemovePtr.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -namespace sb::di::details::utils -{ - template using RemovePtr = std::remove_pointer; - - template using RemovePtrT = typename RemovePtr::type; -} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 84ead1d..ec06f10 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -7,12 +7,8 @@ #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" -#include "SevenBit/DI/Details/Factories/UniquePtrServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" -#include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" -#include "SevenBit/DI/Details/Utils/IsInPlaceObject.hpp" -#include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" @@ -109,6 +105,7 @@ namespace sb::di static ServiceDescriptor describe(const ServiceLifeTime lifetime) { details::utils::Assert::inheritance(); + auto factory = std::make_unique>(); return {typeid(TService), lifetime, std::move(factory)}; } @@ -162,6 +159,7 @@ namespace sb::di static ServiceDescriptor describeSingleton(TImplementation *service) { details::utils::Assert::inheritance(); + auto factory = std::make_unique>(service); return {typeid(TService), ServiceLifeTimes::Singleton, std::move(factory)}; } @@ -344,54 +342,22 @@ namespace sb::di template static ServiceDescriptor describeFrom(const ServiceLifeTime lifetime, FactoryFcn &&factoryFcn) { - auto factory = makeFactoryFrom(std::forward(factoryFcn)); - auto serviceTypeId = std::is_void_v ? factory->getServiceTypeId() : TypeId(typeid(TService)); - return {serviceTypeId, lifetime, std::move(factory)}; + using Factory = details::factories::ServiceFcnFactory; + using TImplementation = typename Factory::ServiceType; + using TRealService = std::conditional_t, TImplementation, TService>; + details::utils::Assert::factoryInheritance(); + + auto factory = std::make_unique(std::forward(factoryFcn)); + return {typeid(TRealService), lifetime, std::move(factory)}; } template static ServiceDescriptor describeAlias() { - details::utils::Assert::isNotSame(); - details::utils::Assert::inheritance(); + details::utils::Assert::aliasNotSame(); + details::utils::Assert::aliasInheritance(); + auto factory = std::make_unique>(); return {typeid(TAlias), ServiceLifeTimes::Scoped, std::move(factory), true}; } - - private: - template static IServiceFactory::Ptr makeFactoryFrom(FactoryFcn &&factoryFcn) - { - using ReturnType = typename details::helpers::ServiceFactoryInvoker::ReturnType; - if constexpr (details::utils::IsUniquePtrV) - { - using Factory = details::factories::UniquePtrServiceFcnFactory; - tryCheckFactoryInheritance(); - return std::make_unique(std::forward(factoryFcn)); - } - else if constexpr (details::utils::IsInPlaceObjectConstructableV) - { - using Factory = details::factories::ServiceFcnFactory; - tryCheckFactoryInheritance(); - return std::make_unique(std::forward(factoryFcn)); - } - else - { - notSupportedReturnType(); - return nullptr; - } - } - - template static void tryCheckFactoryInheritance() - { - if constexpr (!std::is_void_v) - { - details::utils::Assert::inheritance(); - } - } - - template static void notSupportedReturnType() - { - static_assert(details::utils::notSupportedType, - "Service factory return type must be std::unique_ptr or movable/copyable object"); - } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index b4ffe3c..785c236 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -49,12 +49,16 @@ namespace sb::di */ [[nodiscard]] TypeId getImplementationTypeId() const; - [[nodiscard]] bool isAlias() const; /** * @brief Get the service implementation factory */ [[nodiscard]] const IServiceFactory &getImplementationFactory() const; + /** + * @brief Check if service is alias + */ + [[nodiscard]] bool isAlias() const; + bool operator!=(const ServiceDescriptor &descriptor) const; bool operator==(const ServiceDescriptor &descriptor) const; }; diff --git a/Tests/Unit/Containers/ServiceDescriptorListTest.cpp b/Tests/Unit/Containers/ServiceDescriptorListTest.cpp index 7ea21b7..b185f8f 100644 --- a/Tests/Unit/Containers/ServiceDescriptorListTest.cpp +++ b/Tests/Unit/Containers/ServiceDescriptorListTest.cpp @@ -34,6 +34,43 @@ TEST_F(ServiceDescriptorListTest, ShouldAddServiceDescriptors) EXPECT_NO_THROW(act()); } +TEST_F(ServiceDescriptorListTest, ShouldAddServiceAliasDescriptors) +{ + sb::di::details::containers::ServiceDescriptorList list( + sb::di::ServiceDescriber::describeAlias()); + + auto act = [&] { + list.add(sb::di::ServiceDescriber::describeAlias()); + list.add(sb::di::ServiceDescriber::describeAlias()); + }; + + EXPECT_NO_THROW(act()); +} + +TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch1) +{ + sb::di::details::containers::ServiceDescriptorList list( + sb::di::ServiceDescriber::describeAlias()); + + list.add(sb::di::ServiceDescriber::describeAlias()); + + auto act = [&] { list.add(sb::di::ServiceDescriber::describeScoped()); }; + + EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); +} + +TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch2) +{ + sb::di::details::containers::ServiceDescriptorList list( + sb::di::ServiceDescriber::describeSingleton()); + + list.add(sb::di::ServiceDescriber::describeSingleton()); + + auto act = [&] { list.add(sb::di::ServiceDescriber::describeAlias()); }; + + EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); +} + TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorLifeTimeMismatch) { sb::di::details::containers::ServiceDescriptorList list( diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index 979bc20..633b157 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceFactory.hpp" #include "SevenBit/DI/IServiceInstance.hpp" class ServiceInstanceListTest : public testing::Test diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp new file mode 100644 index 0000000..fa2a7b4 --- /dev/null +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -0,0 +1,117 @@ +#include +#include + +#include "../../Helpers/Classes/Basic.hpp" +#include "../../Helpers/Classes/CirularDependency.hpp" +#include "../../Helpers/Classes/Inherit.hpp" +#include "../../Helpers/Mocks/ServiceProviderMock.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class ServiceInstanceCreatorTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + ServiceInstanceCreatorTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~ServiceInstanceCreatorTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + const auto instance = creator.createInstance(descriptor, false); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); +} + +TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) +{ + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 test; + const sb::di::details::services::ExternalService external{&test}; + + const auto instance = creator.createInstanceAlias(typeid(TestInheritClass3), &external); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass3)); +} + +TEST_F(ServiceInstanceCreatorTest, ShouldFailForNullProvider) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::NullPointerException); +} + +TEST_F(ServiceInstanceCreatorTest, ShouldFailForInvalidInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(nullptr); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::InvalidServiceException); +} + +TEST_F(ServiceInstanceCreatorTest, ShouldFailForCirculatDependency) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyA)})) + .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + creator.createInstance(descriptor, false); + return nullptr; + })); + + EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyB)})) + .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + creator.createInstance(descriptor, false); + return nullptr; + })); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::CircularDependencyException); +} + +TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) +{ + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 *test = nullptr; + const sb::di::details::services::ExternalService external{test}; + + EXPECT_THROW(creator.createInstanceAlias(typeid(TestInheritClass3), &external), sb::di::InvalidServiceException); +} diff --git a/Tests/Unit/Core/ServiceInstanceProviderTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderTest.cpp index f235456..071f862 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderTest.cpp @@ -313,14 +313,11 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstance) sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestClass1)), - // sb::di::ServiceNotFoundException); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestClass2)), - // sb::di::ServiceNotFoundException); - // EXPECT_NO_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestClass3))); - // EXPECT_TRUE(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestClass3))); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestClass4)), - // sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestClass1)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestClass2)), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createInstance(typeid(TestClass3))); + EXPECT_TRUE(provider.createInstance(typeid(TestClass3))); + EXPECT_THROW(provider.createInstance(typeid(TestClass4)), sb::di::ServiceNotFoundException); } TEST_F(ServiceInstanceProviderTest, ShouldCreateInheritedInstance) @@ -335,14 +332,11 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInheritedInstance) sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestInheritClass1)), - // sb::di::ServiceNotFoundException); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestInheritClass2)), - // sb::di::ServiceNotFoundException); - // EXPECT_NO_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestInheritClass3))); - // EXPECT_TRUE(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestInheritClass3))); - // EXPECT_THROW(provider.sb::di::IServiceInstanceProvider::createInstance(typeid(TestInheritClass4)), - // sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass1)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass2)), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createInstance(typeid(TestInheritClass3))); + EXPECT_TRUE(provider.createInstance(typeid(TestInheritClass3))); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass4)), sb::di::ServiceNotFoundException); } TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstanceInPlace) diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp new file mode 100644 index 0000000..278db98 --- /dev/null +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -0,0 +1,117 @@ +#include +#include + +#include "../../Helpers/Classes/Basic.hpp" +#include "../../Helpers/Classes/CirularDependency.hpp" +#include "../../Helpers/Classes/Inherit.hpp" +#include "../../Helpers/Mocks/ServiceProviderMock.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class ServiceInstanceResolverTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + ServiceInstanceResolverTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~ServiceInstanceResolverTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(ServiceInstanceResolverTest, ShouldCreateInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + const auto instance = creator.createInstance(descriptor, false); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceAlias) +{ + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 test; + const sb::di::details::services::ExternalService external{&test}; + + const auto instance = creator.createInstanceAlias(typeid(TestInheritClass3), &external); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass3)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldFailForNullProvider) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::NullPointerException); +} + +TEST_F(ServiceInstanceResolverTest, ShouldFailForInvalidInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(nullptr); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::InvalidServiceException); +} + +TEST_F(ServiceInstanceResolverTest, ShouldFailForCirculatDependency) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyA)})) + .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + creator.createInstance(descriptor, false); + return nullptr; + })); + + EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyB)})) + .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + creator.createInstance(descriptor, false); + return nullptr; + })); + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::CircularDependencyException); +} + +TEST_F(ServiceInstanceResolverTest, ShouldFailCreateInstanceAlias) +{ + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 *test = nullptr; + const sb::di::details::services::ExternalService external{test}; + + EXPECT_THROW(creator.createInstanceAlias(typeid(TestInheritClass3), &external), sb::di::InvalidServiceException); +} diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index a48bcc1..271b65e 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -23,14 +23,6 @@ class ServiceFcnFactoryTest : public testing::Test static void TearDownTestSuite() {} }; -TEST_F(ServiceFcnFactoryTest, ShouldNotCompileWrongFactoryScheme) -{ - // TestClass1 test; - // auto fcn = [&](auto f) { return std::make_unique(); }; - - // sb::di::details::ServiceFcnFactory factory{std::move(fcn)}; -} - TEST_F(ServiceFcnFactoryTest, ShouldCreateService) { ServiceProviderMock mock; @@ -41,8 +33,8 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateService) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - // EXPECT_TRUE(dynamic_cast *>(instance.get())); - // EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); + EXPECT_TRUE(dynamic_cast *>(instance.get())); + EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -264,9 +256,9 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq2Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - // EXPECT_TRUE( - // dynamic_cast *>(instance.get())); - // EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); + EXPECT_TRUE( + dynamic_cast *>(instance.get())); + EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -310,8 +302,8 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - // EXPECT_TRUE(dynamic_cast - // *>(instance.get())); EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); + EXPECT_TRUE(dynamic_cast *>(instance.get())); + EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } @@ -358,7 +350,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - // EXPECT_TRUE(dynamic_cast - // *>(instance.get())); EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); + EXPECT_TRUE(dynamic_cast *>(instance.get())); + EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } diff --git a/Tests/Unit/Factories/VoidServiceFactoryTest.cpp b/Tests/Unit/Factories/VoidServiceFactoryTest.cpp new file mode 100644 index 0000000..7a2afe1 --- /dev/null +++ b/Tests/Unit/Factories/VoidServiceFactoryTest.cpp @@ -0,0 +1,44 @@ +#include + +#include "../../Helpers/Classes/Basic.hpp" +#include "../../Helpers/Mocks/ServiceProviderMock.hpp" +#include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" +#include "SevenBit/DI/Exceptions.hpp" + +class VoidServiceFactoryTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + VoidServiceFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~VoidServiceFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(VoidServiceFactoryTest, ShouldCreateVoidService) +{ + TestClass1 test; + ServiceProviderMock mock; + const sb::di::details::factories::VoidServiceFactory factory{}; + + const auto instance = factory.createInstance(mock, false); + + EXPECT_FALSE(instance); +} + +TEST_F(VoidServiceFactoryTest, ShouldCreateVoidInPlaceService) +{ + TestClass1 test; + ServiceProviderMock mock; + const sb::di::details::factories::VoidServiceFactory factory{}; + + const auto instance = factory.createInstance(mock, true); + + EXPECT_FALSE(instance); +} diff --git a/Tests/Unit/Helpers/ServiceFactoryInvoker.cpp b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp similarity index 82% rename from Tests/Unit/Helpers/ServiceFactoryInvoker.cpp rename to Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp index 8eea2ac..e138a34 100644 --- a/Tests/Unit/Helpers/ServiceFactoryInvoker.cpp +++ b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp @@ -6,23 +6,23 @@ #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/ServiceProvider.hpp" -class ServiceFactoryInvoker : public testing::Test +class ServiceFactoryInvokerTest : public testing::Test { protected: static void TearUpTestSuite() {} - ServiceFactoryInvoker() {} + ServiceFactoryInvokerTest() {} void SetUp() override {} void TearDown() override {} - ~ServiceFactoryInvoker() override = default; + ~ServiceFactoryInvokerTest() override = default; static void TearDownTestSuite() {} }; -TEST_F(ServiceFactoryInvoker, ShouldInvokeFuncFactory) +TEST_F(ServiceFactoryInvokerTest, ShouldInvokeFuncFactory) { ServiceProviderMock mock; sb::di::details::services::InPlaceService test1; diff --git a/Tests/Unit/ServiceCollectionTest.cpp b/Tests/Unit/ServiceCollectionTest.cpp index 35f2563..b398f24 100644 --- a/Tests/Unit/ServiceCollectionTest.cpp +++ b/Tests/Unit/ServiceCollectionTest.cpp @@ -4,7 +4,6 @@ #include "../Helpers/Classes/Basic.hpp" #include "../Helpers/Classes/Complex.hpp" -#include "../Helpers/Classes/Dependencies.hpp" #include "../Helpers/Classes/Inherit.hpp" #include "SevenBit/DI/ServiceCollection.hpp" @@ -37,6 +36,8 @@ TEST_F(ServiceCollectionTest, ShouldAddServices) services.addTransient(); services.addTransient(); + + services.addAlias(); }; EXPECT_NO_THROW(act()); } @@ -289,6 +290,8 @@ TEST_F(ServiceCollectionTest, ShouldAddDescriptor) services.add(sb::di::ServiceDescriber::describeTransient()); services.add(sb::di::ServiceDescriber::describeTransient()); + + services.add(sb::di::ServiceDescriber::describeAlias()); }; EXPECT_NO_THROW(act()); @@ -445,11 +448,13 @@ TEST_F(ServiceCollectionTest, ShouldAddBasicServices) services.addSingleton(); services.addScoped(); services.addTransient(); + services.addAlias(); + EXPECT_TRUE(services.contains()); EXPECT_TRUE(services.contains()); EXPECT_TRUE(services.contains()); EXPECT_TRUE(services.contains()); - EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services.size(), 4); } TEST_F(ServiceCollectionTest, ShouldAddInheritedServices) @@ -464,6 +469,18 @@ TEST_F(ServiceCollectionTest, ShouldAddInheritedServices) EXPECT_EQ(services.size(), 3); } +TEST_F(ServiceCollectionTest, ShouldAddInheritedAliasServices) +{ + sb::di::ServiceCollection services; + + services.addAlias(); + services.addAlias(); + services.addAlias(); + + EXPECT_TRUE(services.contains()); + EXPECT_EQ(services.size(), 3); +} + TEST_F(ServiceCollectionTest, ShouldAddExternalSingleton) { sb::di::ServiceCollection services; @@ -562,10 +579,3 @@ TEST_F(ServiceCollectionTest, ShouldAddInheritedServicesWithFactory) EXPECT_TRUE(services.contains()); EXPECT_EQ(services.size(), 3); } - -TEST_F(ServiceCollectionTest, ShouldNotCompileDueToNotInheritedServices) -{ - sb::di::ServiceCollection services; - - // services.addTransient(); -} diff --git a/Tests/Unit/ServiceDescriberTest.cpp b/Tests/Unit/ServiceDescriberTest.cpp index d985bcf..4b1e27f 100644 --- a/Tests/Unit/ServiceDescriberTest.cpp +++ b/Tests/Unit/ServiceDescriberTest.cpp @@ -30,6 +30,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonCtorService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonCtorInterfaceService) @@ -39,6 +40,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonCtorInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedCtorService) @@ -48,6 +50,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeScopedCtorService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedCtorInterfaceService) @@ -57,6 +60,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeScopedCtorInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeTransientCtorService) @@ -66,6 +70,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeTransientCtorService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeTransientCtorInterfaceService) @@ -75,6 +80,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeTransientCtorInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonExternalService) @@ -85,6 +91,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonExternalService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonExternalInterfaceService) @@ -95,6 +102,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonExternalInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonFcnService) @@ -107,6 +115,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonFcnService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonEmptyFcnService) @@ -116,6 +125,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonEmptyFcnService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonFcnInterfaceService) @@ -128,6 +138,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonFcnInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeSingletonEmptyFcnInterfaceService) @@ -138,6 +149,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeSingletonEmptyFcnInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedFcnService) @@ -150,6 +162,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeScopedFcnService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedEmptyFcnService) @@ -159,6 +172,7 @@ TEST_F(ServiceDescriberTest, ShouldDescribeScopedEmptyFcnService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedFcnInterfaceService) @@ -171,16 +185,18 @@ TEST_F(ServiceDescriberTest, ShouldDescribeScopedFcnInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeScopedEmptyFcnInterfaceService) { - const auto descriptor = sb::di::ServiceDescriber::describeScopedFrom( - [] { return TestInheritClass5(); }); + const auto descriptor = + sb::di::ServiceDescriber::describeScopedFrom([] { return TestInheritClass5(); }); EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeTransientFcnService) @@ -193,16 +209,17 @@ TEST_F(ServiceDescriberTest, ShouldDescribeTransientFcnService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeEmptyTransientFcnService) { - const auto descriptor = - sb::di::ServiceDescriber::describeTransientFrom([] { return TestClass1(); }); + const auto descriptor = sb::di::ServiceDescriber::describeTransientFrom([] { return TestClass1(); }); EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeTransientFcnInterfaceService) @@ -215,14 +232,26 @@ TEST_F(ServiceDescriberTest, ShouldDescribeTransientFcnInterfaceService) EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); } TEST_F(ServiceDescriberTest, ShouldDescribeTransientEmptyFcnInterfaceService) { - const auto descriptor = sb::di::ServiceDescriber::describeTransientFrom( - [] { return TestInheritClass5(); }); + const auto descriptor = + sb::di::ServiceDescriber::describeTransientFrom([] { return TestInheritClass5(); }); EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::transient()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_FALSE(descriptor.isAlias()); +} + +TEST_F(ServiceDescriberTest, ShouldDescribeAliasService) +{ + const auto descriptor = sb::di::ServiceDescriber::describeAlias(); + + EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::scoped()); + EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestInheritClass1)); + EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(descriptor.isAlias()); } diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 20247c9..6b6b1b7 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -55,6 +55,21 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromDescriptor) EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); EXPECT_EQ(&descriptor.getImplementationFactory(), factoryPtr); + EXPECT_FALSE(descriptor.isAlias()); +} + +TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) +{ + auto factory = std::make_unique>(); + const auto factoryPtr = factory.get(); + const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), + std::move(factory), true}; + + EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); + EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); + EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); + EXPECT_EQ(&descriptor.getImplementationFactory(), factoryPtr); + EXPECT_TRUE(descriptor.isAlias()); } TEST_F(ServiceDescriptorTest, ShouldCompareDescriptors) diff --git a/Tests/Unit/ServiceLifeTimeTest.cpp b/Tests/Unit/ServiceLifeTimeTest.cpp index 3e5170e..968f2f6 100644 --- a/Tests/Unit/ServiceLifeTimeTest.cpp +++ b/Tests/Unit/ServiceLifeTimeTest.cpp @@ -1,6 +1,6 @@ #include -#include "SevenBit/DI/ServiceLifeTime.hpp" +#include "SevenBit/DI/ServiceLifeTimes.hpp" class ServiceLifeTime : public testing::Test { @@ -29,6 +29,14 @@ TEST_F(ServiceLifeTime, ShouldConstructProperLifetime) EXPECT_NO_THROW(act()); } +TEST_F(ServiceLifeTime, ShouldFailConstructLifetime) +{ + EXPECT_THROW(sb::di::ServiceLifeTime{sb::di::ServiceLifeTime::Count}, sb::di::InjectorException); + EXPECT_THROW(sb::di::ServiceLifeTime{static_cast(-123)}, sb::di::InjectorException); + EXPECT_THROW(sb::di::ServiceLifeTime{static_cast(123)}, sb::di::InjectorException); + EXPECT_THROW(sb::di::ServiceLifeTime{static_cast(-1)}, sb::di::InjectorException); +} + TEST_F(ServiceLifeTime, ShouldConstructProperLifetimeUsingFactories) { auto act = [] { @@ -40,9 +48,20 @@ TEST_F(ServiceLifeTime, ShouldConstructProperLifetimeUsingFactories) EXPECT_NO_THROW(act()); } +TEST_F(ServiceLifeTime, ShouldConstructProperLifetimeUsingList) +{ + auto act = [] { + auto singleton = sb::di::ServiceLifeTimes::Singleton; + auto scoped = sb::di::ServiceLifeTimes::Scoped; + auto transient = sb::di::ServiceLifeTimes::Transient; + }; + + EXPECT_NO_THROW(act()); +} + TEST_F(ServiceLifeTime, ShouldCheckLifetime) { - const auto lifeTime = sb::di::ServiceLifeTime::singleton(); + constexpr auto lifeTime = sb::di::ServiceLifeTime::singleton(); EXPECT_TRUE(lifeTime.isSingleton()); EXPECT_TRUE(lifeTime.is(sb::di::ServiceLifeTime::Singleton)); diff --git a/Tests/Unit/Services/AliasServiceTest.cpp b/Tests/Unit/Services/AliasServiceTest.cpp new file mode 100644 index 0000000..20c5a0f --- /dev/null +++ b/Tests/Unit/Services/AliasServiceTest.cpp @@ -0,0 +1,80 @@ +#include + +#include "../../Helpers/Classes/Basic.hpp" +#include "SevenBit/DI/Details/Services/AliasService.hpp" +#include "SevenBit/DI/Exceptions.hpp" + +class AliasServiceTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + AliasServiceTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~AliasServiceTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(AliasServiceTest, ShouldCreateExternalService) +{ + TestClass1 test; + const sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; + + EXPECT_TRUE(service); + EXPECT_TRUE(service.isValid()); + EXPECT_EQ(service.get(), &test); + EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); +} + +TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalService) +{ + TestClass1 test; + sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; + + EXPECT_TRUE(service); + EXPECT_TRUE(service.isValid()); + EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); +} + +TEST_F(AliasServiceTest, ShouldFailMoveOutExternalService) +{ + TestClass1 test; + sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; + + EXPECT_TRUE(service); + EXPECT_TRUE(service.isValid()); + EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); +} + +TEST_F(AliasServiceTest, ShouldCreateExternalNullService) +{ + sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; + + EXPECT_FALSE(service); + EXPECT_FALSE(service.isValid()); + EXPECT_FALSE(service.get()); + EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); +} + +TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) +{ + sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; + + EXPECT_FALSE(service); + EXPECT_FALSE(service.isValid()); + EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); +} + +TEST_F(AliasServiceTest, ShouldFailMoveOutExternalNullService) +{ + sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; + + EXPECT_FALSE(service); + EXPECT_FALSE(service.isValid()); + EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); +} diff --git a/Tests/Unit/Services/ExternalServiceTest.cpp b/Tests/Unit/Services/ExternalServiceTest.cpp index 77d2270..a36cf34 100644 --- a/Tests/Unit/Services/ExternalServiceTest.cpp +++ b/Tests/Unit/Services/ExternalServiceTest.cpp @@ -31,23 +31,6 @@ TEST_F(ExternalServiceTest, ShouldCreateExternalService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(ExternalServiceTest, ShouldUpdateExternalService) -{ - TestClass1 test; - sb::di::details::services::ExternalService service{&test}; - - EXPECT_TRUE(service); - EXPECT_TRUE(service.isValid()); - EXPECT_EQ(service.get(), &test); - - TestClass1 test2; - service.update(&test2); - - EXPECT_TRUE(service); - EXPECT_TRUE(service.isValid()); - EXPECT_EQ(service.get(), &test2); -} - TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalService) { TestClass1 test; diff --git a/Tests/Unit/Utils/CheckTest.cpp b/Tests/Unit/Utils/CheckTest.cpp index d38144d..f72b9d3 100644 --- a/Tests/Unit/Utils/CheckTest.cpp +++ b/Tests/Unit/Utils/CheckTest.cpp @@ -3,6 +3,7 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "../../Helpers/Classes/Basic.hpp" +#include "../../Helpers/Classes/Inherit.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" @@ -23,6 +24,36 @@ class CheckTest : public testing::Test static void TearDownTestSuite() {} }; +TEST_F(CheckTest, ShouldCheckNotNull) +{ + EXPECT_FALSE(sb::di::details::utils::Check::notNull(nullptr)); + EXPECT_FALSE(sb::di::details::utils::Check::notNull(std::unique_ptr())); + EXPECT_FALSE(sb::di::details::utils::Check::notNull(std::shared_ptr())); + + int intTest = 123; + EXPECT_TRUE(sb::di::details::utils::Check::notNull(&intTest)); + EXPECT_TRUE(sb::di::details::utils::Check::notNull(std::make_unique(intTest))); + EXPECT_TRUE(sb::di::details::utils::Check::notNull(std::make_shared(intTest))); +} + +TEST_F(CheckTest, ShouldCheckEnum) +{ + enum TestEnum + { + A, + B, + C, + Count, + }; + EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(123))); + EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(-123))); + EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(-1))); + EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(TestEnum::Count)); + EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::A)); + EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::B)); + EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::C)); +} + TEST_F(CheckTest, ShouldCheckInstanceValidity) { TestClass1 test; diff --git a/Tests/Unit/Utils/InheritanceTest.cpp b/Tests/Unit/Utils/InheritanceTest.cpp new file mode 100644 index 0000000..4cfacd6 --- /dev/null +++ b/Tests/Unit/Utils/InheritanceTest.cpp @@ -0,0 +1,40 @@ +#include + +#include "SevenBit/DI/Details/Utils/Check.hpp" + +#include "../../Helpers/Classes/Complex.hpp" +#include "SevenBit/DI/Details/Utils/Inheritance.hpp" + +class InheritanceTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + InheritanceTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~InheritanceTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(InheritanceTest, ShouldCheckInheritance) +{ + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_FALSE((sb::di::details::utils::InheritanceV)); + EXPECT_FALSE((sb::di::details::utils::InheritanceV)); + EXPECT_FALSE((sb::di::details::utils::InheritanceV)); + EXPECT_FALSE((sb::di::details::utils::InheritanceV)); + EXPECT_FALSE((sb::di::details::utils::InheritanceV)); +} diff --git a/Tests/Unit/Utils/IsInPlaceObject.cpp b/Tests/Unit/Utils/IsInPlaceObjectTest.cpp similarity index 100% rename from Tests/Unit/Utils/IsInPlaceObject.cpp rename to Tests/Unit/Utils/IsInPlaceObjectTest.cpp diff --git a/Tests/Unit/Utils/IsUniquePtr.cpp b/Tests/Unit/Utils/IsUniquePtrTest.cpp similarity index 100% rename from Tests/Unit/Utils/IsUniquePtr.cpp rename to Tests/Unit/Utils/IsUniquePtrTest.cpp diff --git a/Tests/Unit/Utils/RemoveUniquePtrTest.cpp b/Tests/Unit/Utils/RemoveUniquePtrTest.cpp new file mode 100644 index 0000000..c02b8e8 --- /dev/null +++ b/Tests/Unit/Utils/RemoveUniquePtrTest.cpp @@ -0,0 +1,32 @@ +#include + +#include "SevenBit/DI/Details/Utils/Check.hpp" + +#include "../../Helpers/Classes/Complex.hpp" +#include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" + +class RemoveUniquePtrTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + RemoveUniquePtrTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~RemoveUniquePtrTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(RemoveUniquePtrTest, ShouldRemoveUniquePtrTest) +{ + EXPECT_TRUE((std::is_same_v>, + TestComplexClass1>)); + EXPECT_TRUE((std::is_same_v>, + TestComplexClass2>)); + EXPECT_FALSE((std::is_same_v>, + TestComplexClass1>)); +} diff --git a/Tests/Unit/Utils/RequireTest.cpp b/Tests/Unit/Utils/RequireTest.cpp index c084aa8..7031493 100644 --- a/Tests/Unit/Utils/RequireTest.cpp +++ b/Tests/Unit/Utils/RequireTest.cpp @@ -50,7 +50,25 @@ TEST_F(RequireTest, ShouldFailRequireNotNull) EXPECT_THROW(sb::di::details::utils::Require::notNullAndGet(std::move(testSPtr)), sb::di::NullPointerException); } -TEST_F(RequireTest, ShoulRequireInstanceValidity) +TEST_F(RequireTest, ShouldRequireValidEnum) +{ + enum TestEnum + { + A, + B, + C, + Count, + }; + EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(123)), sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(-123)), sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(-1)), sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::Require::validEnum(TestEnum::Count), sb::di::InjectorException); + EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::A)); + EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::B)); + EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::C)); +} + +TEST_F(RequireTest, ShoulRequireValidInstance) { TestClass1 test; EXPECT_THROW(sb::di::details::utils::Require::validInstance(nullptr), sb::di::NullPointerException); From 41be1cd2af2358fcbfd64a603dafa5567399a69b Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 29 Jan 2024 20:14:09 +0100 Subject: [PATCH 26/45] remove unused functions --- .../SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp | 4 ---- Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp | 2 +- Include/SevenBit/DI/Details/Utils/Check.hpp | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index e63a95f..bdaf8b5 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" @@ -13,7 +10,6 @@ #include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" #include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core { diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 5d91248..f227e6f 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -10,7 +10,7 @@ #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" #include "SevenBit/DI/IServiceInstanceProvider.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" +#include "SevenBit/DI/ServiceProviderOptions.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 98ceb8d..8e1fc7d 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -9,10 +9,6 @@ namespace sb::di::details::utils { struct EXPORT Check { - template constexpr static bool isSame() { return std::is_same_v; } - - template constexpr static bool inheritance() {} - template constexpr static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } template constexpr static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } From be21bf59ce1a946abd5ce5aab810a8ef76a9b232 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 29 Jan 2024 20:38:57 +0100 Subject: [PATCH 27/45] update checkouts --- .github/workflows/DevCI.yml | 2 +- .github/workflows/Linux.yml | 2 +- .github/workflows/MacOs.yml | 2 +- .github/workflows/Windows.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/DevCI.yml b/.github/workflows/DevCI.yml index 02d91d6..d1ebb1f 100644 --- a/.github/workflows/DevCI.yml +++ b/.github/workflows/DevCI.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index 705b2af..f640dfb 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -58,7 +58,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create Build Environment env: diff --git a/.github/workflows/MacOs.yml b/.github/workflows/MacOs.yml index 3e97d1a..26fdb33 100644 --- a/.github/workflows/MacOs.yml +++ b/.github/workflows/MacOs.yml @@ -36,7 +36,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create Build Environment if: matrix.compiler.tool != 'apple-clang' diff --git a/.github/workflows/Windows.yml b/.github/workflows/Windows.yml index 3857798..8782dac 100644 --- a/.github/workflows/Windows.yml +++ b/.github/workflows/Windows.yml @@ -53,7 +53,7 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Create Build Environment if: matrix.compiler.tool != 'msvc' From 71f180f40ab7265630ea3f3d60f183eba0c75a50 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 30 Jan 2024 18:06:37 +0100 Subject: [PATCH 28/45] update tests --- .../Containers/Impl/ServiceDescriptorsMap.hpp | 4 +- Include/SevenBit/DI/ServiceLifeTime.hpp | 2 +- Tests/Helpers/Classes/Inherit.hpp | 7 +- .../Containers/ServiceDescriptorsMapTest.cpp | 13 + ...pp => ServiceInstanceProviderRootTest.cpp} | 186 ++++++-- .../Unit/Core/ServiceInstanceResolverTest.cpp | 400 ++++++++++++++++-- 6 files changed, 538 insertions(+), 74 deletions(-) rename Tests/Unit/Core/{ServiceInstanceProviderTest.cpp => ServiceInstanceProviderRootTest.cpp} (63%) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp index b14b332..688ad13 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp @@ -13,8 +13,8 @@ namespace sb::di::details::containers INLINE void ServiceDescriptorsMap::add(ServiceDescriptor descriptor) { - return _registeredServicesCheck ? addDescriptorWithCheck(std::move(descriptor)) - : addDescriptor(std::move(descriptor)); + return _registeredServicesCheck && !descriptor.isAlias() ? addDescriptorWithCheck(std::move(descriptor)) + : addDescriptor(std::move(descriptor)); } INLINE void ServiceDescriptorsMap::seal() { _registeredServicesCheck.reset(); } diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index de5d102..9d9e93d 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -10,7 +10,7 @@ namespace sb::di { public: /** - * @brief 4 types of available service lifetimes + * @brief 3 types of available service lifetimes */ enum Type { diff --git a/Tests/Helpers/Classes/Inherit.hpp b/Tests/Helpers/Classes/Inherit.hpp index 7132881..f6ca629 100644 --- a/Tests/Helpers/Classes/Inherit.hpp +++ b/Tests/Helpers/Classes/Inherit.hpp @@ -25,8 +25,11 @@ struct TestInheritClass6 : TestInheritClass5 { int number() override { return 6; } }; - -struct TestInheritClass7 final : TestInheritClass6 +struct TestInheritClass7 : TestInheritClass6 { int number() override { return 7; } }; +struct TestInheritClass8 final : TestInheritClass7 +{ + int number() override { return 8; } +}; diff --git a/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp b/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp index f4fad9a..ffbdfc3 100644 --- a/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp +++ b/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp @@ -49,6 +49,19 @@ TEST_F(ServiceDescriptorsMapTest, ShouldCheckUniqeness) EXPECT_THROW(act(), sb::di::ServiceAlreadyRegisteredException); } +TEST_F(ServiceDescriptorsMapTest, ShouldCheckUniqenessForAlias) +{ + std::vector _descriptors; + sb::di::details::containers::ServiceDescriptorsMap map{_descriptors.begin(), _descriptors.end(), true}; + + map.add(sb::di::ServiceDescriber::describeAlias()); + map.add(sb::di::ServiceDescriber::describeAlias()); + + auto act = [&] { map.add(sb::di::ServiceDescriber::describeAlias()); }; + + EXPECT_NO_THROW(act()); +} + TEST_F(ServiceDescriptorsMapTest, ShouldNotCheckUniqeness) { std::vector _descriptors; diff --git a/Tests/Unit/Core/ServiceInstanceProviderTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp similarity index 63% rename from Tests/Unit/Core/ServiceInstanceProviderTest.cpp rename to Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp index 071f862..a7cbaf6 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp @@ -9,23 +9,23 @@ #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceCollection.hpp" -class ServiceInstanceProviderTest : public testing::Test +class ServiceInstanceProviderRootTest : public testing::Test { protected: static void SetUpTestSuite() {} - ServiceInstanceProviderTest() {} + ServiceInstanceProviderRootTest() {} void SetUp() override {} void TearDown() override {} - ~ServiceInstanceProviderTest() override = default; + ~ServiceInstanceProviderRootTest() override = default; static void TearDownTestSuite() {} }; -TEST_F(ServiceInstanceProviderTest, ShouldGetOptions) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetOptions) { ServiceProviderMock mock; std::vector describers; @@ -41,7 +41,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetOptions) EXPECT_TRUE(options.checkServiceGlobalUniqueness); } -TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAlreadyRegisteredService) { ServiceProviderMock mock; std::vector describers; @@ -58,7 +58,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredSe EXPECT_THROW(act(), sb::di::ServiceAlreadyRegisteredException); } -TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredInheritedService) +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAlreadyRegisteredInheritedService) { ServiceProviderMock mock; std::vector describers; @@ -75,7 +75,41 @@ TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredIn EXPECT_THROW(act(), sb::di::ServiceAlreadyRegisteredException); } -TEST_F(ServiceInstanceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAliasMissmatchInheritedService) +{ + ServiceProviderMock mock; + std::vector describers; + + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + + auto act = [&] { + sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); + provider.init(mock); + }; + + EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); +} + +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAliasMissmatchInheritedService2) +{ + ServiceProviderMock mock; + std::vector describers; + + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + + auto act = [&] { + sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); + provider.init(mock); + }; + + EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); +} + +TEST_F(ServiceInstanceProviderRootTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) { ServiceProviderMock mock; std::vector describers; @@ -95,7 +129,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegistere EXPECT_NO_THROW(act()); } -TEST_F(ServiceInstanceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegisteredInheritedService) +TEST_F(ServiceInstanceProviderRootTest, ShouldNotFailGetServiceDueToAlreadyRegisteredInheritedService) { ServiceProviderMock mock; std::vector describers; @@ -115,7 +149,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegistere EXPECT_NO_THROW(act()); } -TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToLifetimeMissmatchInheritedService) +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToLifetimeMissmatchInheritedService) { ServiceProviderMock mock; std::vector describers; @@ -132,7 +166,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldFailGetServiceDueToLifetimeMissmatchIn EXPECT_THROW(act(), sb::di::ServiceLifeTimeMismatchException); } -TEST_F(ServiceInstanceProviderTest, ShouldTryGetInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldTryGetInstance) { ServiceProviderMock mock; std::vector describers; @@ -150,25 +184,29 @@ TEST_F(ServiceInstanceProviderTest, ShouldTryGetInstance) EXPECT_FALSE(provider.tryGetInstance(typeid(TestClass4))); } -TEST_F(ServiceInstanceProviderTest, ShouldTryGetInheritedInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldTryGetInheritedInstance) { ServiceProviderMock mock; std::vector describers; - describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); EXPECT_TRUE(provider.tryGetInstance(typeid(TestInheritClass1))); EXPECT_TRUE(provider.tryGetInstance(typeid(TestInheritClass2))); + EXPECT_TRUE(provider.tryGetInstance(typeid(TestInheritClass4))); EXPECT_FALSE(provider.tryGetInstance(typeid(TestInheritClass3))); - EXPECT_FALSE(provider.tryGetInstance(typeid(TestInheritClass4))); + EXPECT_FALSE(provider.tryGetInstance(typeid(TestInheritClass5))); + EXPECT_FALSE(provider.tryGetInstance(typeid(TestInheritClass6))); } -TEST_F(ServiceInstanceProviderTest, ShouldGetInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetInstance) { ServiceProviderMock mock; std::vector describers; @@ -188,34 +226,40 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetInstance) EXPECT_THROW(provider.getInstance(typeid(TestClass4)), sb::di::ServiceNotFoundException); } -TEST_F(ServiceInstanceProviderTest, ShouldGetInheritedInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetInheritedInstance) { ServiceProviderMock mock; std::vector describers; - describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); EXPECT_NO_THROW(provider.getInstance(typeid(TestInheritClass1))); EXPECT_NO_THROW(provider.getInstance(typeid(TestInheritClass2))); + EXPECT_NO_THROW(provider.getInstance(typeid(TestInheritClass4))); EXPECT_TRUE(provider.getInstance(typeid(TestInheritClass1))); EXPECT_TRUE(provider.getInstance(typeid(TestInheritClass2))); + EXPECT_TRUE(provider.getInstance(typeid(TestInheritClass4))); EXPECT_THROW(provider.getInstance(typeid(TestInheritClass3)), sb::di::ServiceNotFoundException); - EXPECT_THROW(provider.getInstance(typeid(TestInheritClass4)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getInstance(typeid(TestInheritClass5)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getInstance(typeid(TestInheritClass6)), sb::di::ServiceNotFoundException); } -TEST_F(ServiceInstanceProviderTest, ShouldGetSelf) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetSelf) { ServiceProviderMock mock; std::vector describers; - describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -224,7 +268,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetSelf) EXPECT_EQ(self.get(), &mock); } -TEST_F(ServiceInstanceProviderTest, ShouldGetInstances) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetInstances) { ServiceProviderMock mock; std::vector describers; @@ -242,7 +286,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetInstances) EXPECT_FALSE(provider.tryGetInstances(typeid(TestClass4))); } -TEST_F(ServiceInstanceProviderTest, ShouldGetInstancesInOrder) +TEST_F(ServiceInstanceProviderRootTest, ShouldGetInstancesInOrder) { ServiceProviderMock mock; std::vector describers; @@ -252,6 +296,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetInstancesInOrder) describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -263,9 +308,35 @@ TEST_F(ServiceInstanceProviderTest, ShouldGetInstancesInOrder) EXPECT_EQ(static_cast(services[2]->get())->number(), 3); EXPECT_EQ(static_cast(services[3]->get())->number(), 4); EXPECT_EQ(static_cast(services[4]->get())->number(), 5); + EXPECT_FALSE(provider.tryGetInstances(typeid(TestInheritClass5))); + EXPECT_FALSE(provider.tryGetInstances(typeid(TestInheritClass4))); +} + +TEST_F(ServiceInstanceProviderRootTest, ShouldGetAliasInstancesInOrder) +{ + ServiceProviderMock mock; + std::vector describers; + + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + + sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); + provider.init(mock); + + auto &services = *provider.tryGetInstances(typeid(TestInheritClass1)); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(static_cast(services[0]->get())->number(), 2); + EXPECT_EQ(static_cast(services[1]->get())->number(), 3); + EXPECT_EQ(static_cast(services[2]->get())->number(), 4); + EXPECT_EQ(static_cast(services[3]->get())->number(), 5); + EXPECT_EQ(static_cast(services[4]->get())->number(), 6); } -TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldTryCreateInstance) { ServiceProviderMock mock; std::vector describers; @@ -283,25 +354,32 @@ TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstance) EXPECT_FALSE(provider.tryCreateInstance(typeid(TestClass4))); } -TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInheritedInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldTryCreateInheritedInstance) { ServiceProviderMock mock; std::vector describers; - describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); - EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass1))); + EXPECT_TRUE(provider.tryCreateInstance(typeid(TestInheritClass1))); EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass2))); EXPECT_TRUE(provider.tryCreateInstance(typeid(TestInheritClass3))); EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass4))); + EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass5))); + EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass6))); + EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass7))); + EXPECT_FALSE(provider.tryCreateInstance(typeid(TestInheritClass8))); } -TEST_F(ServiceInstanceProviderTest, ShouldCreateInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInstance) { ServiceProviderMock mock; std::vector describers; @@ -320,26 +398,32 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstance) EXPECT_THROW(provider.createInstance(typeid(TestClass4)), sb::di::ServiceNotFoundException); } -TEST_F(ServiceInstanceProviderTest, ShouldCreateInheritedInstance) +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInheritedInstance) { ServiceProviderMock mock; std::vector describers; - describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); - EXPECT_THROW(provider.createInstance(typeid(TestInheritClass1)), sb::di::ServiceNotFoundException); + EXPECT_TRUE(provider.createInstance(typeid(TestInheritClass1))); EXPECT_THROW(provider.createInstance(typeid(TestInheritClass2)), sb::di::ServiceNotFoundException); - EXPECT_NO_THROW(provider.createInstance(typeid(TestInheritClass3))); EXPECT_TRUE(provider.createInstance(typeid(TestInheritClass3))); EXPECT_THROW(provider.createInstance(typeid(TestInheritClass4)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass5)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass6)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass7)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstance(typeid(TestInheritClass8)), sb::di::ServiceNotFoundException); } -TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstanceInPlace) +TEST_F(ServiceInstanceProviderRootTest, ShouldTryCreateInstanceInPlace) { ServiceProviderMock mock; std::vector describers; @@ -347,6 +431,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstanceInPlace) describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -355,9 +440,10 @@ TEST_F(ServiceInstanceProviderTest, ShouldTryCreateInstanceInPlace) EXPECT_FALSE(provider.tryCreateInstanceInPlace(typeid(TestClass2))); EXPECT_TRUE(provider.tryCreateInstanceInPlace(typeid(TestClass3))); EXPECT_FALSE(provider.tryCreateInstanceInPlace(typeid(TestClass4))); + EXPECT_FALSE(provider.tryCreateInstanceInPlace(typeid(TestInheritClass5))); } -TEST_F(ServiceInstanceProviderTest, ShouldCreateInstanceInPlace) +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInstanceInPlace) { ServiceProviderMock mock; std::vector describers; @@ -365,6 +451,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstanceInPlace) describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -374,9 +461,10 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstanceInPlace) EXPECT_NO_THROW(provider.createInstanceInPlace(typeid(TestClass3))); EXPECT_TRUE(provider.createInstanceInPlace(typeid(TestClass3))); EXPECT_THROW(provider.createInstanceInPlace(typeid(TestClass4)), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createInstanceInPlace(typeid(TestInheritClass5)), sb::di::ServiceNotFoundException); } -TEST_F(ServiceInstanceProviderTest, ShouldCreateInstances) +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInstances) { ServiceProviderMock mock; std::vector describers; @@ -384,6 +472,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstances) describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -392,9 +481,11 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstances) EXPECT_FALSE(provider.tryCreateInstances(typeid(TestClass2))); EXPECT_EQ(provider.tryCreateInstances(typeid(TestClass3))->size(), 1); EXPECT_FALSE(provider.tryCreateInstances(typeid(TestClass4))); + EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass5))); + EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass6))); } -TEST_F(ServiceInstanceProviderTest, ShouldCreateInstancesInOrder) +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInstancesInOrder) { ServiceProviderMock mock; std::vector describers; @@ -404,6 +495,7 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstancesInOrder) describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); @@ -415,4 +507,30 @@ TEST_F(ServiceInstanceProviderTest, ShouldCreateInstancesInOrder) EXPECT_EQ(static_cast(services[2]->get())->number(), 3); EXPECT_EQ(static_cast(services[3]->get())->number(), 4); EXPECT_EQ(static_cast(services[4]->get())->number(), 5); + EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass5))); + EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass6))); +} + +TEST_F(ServiceInstanceProviderRootTest, ShouldCreateAliasInstancesInOrder) +{ + ServiceProviderMock mock; + std::vector describers; + + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + describers.emplace_back(sb::di::ServiceDescriber::describeAlias()); + + sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); + provider.init(mock); + + auto services = *provider.tryCreateInstances(typeid(TestInheritClass1)); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(static_cast(services[0]->get())->number(), 2); + EXPECT_EQ(static_cast(services[1]->get())->number(), 3); + EXPECT_EQ(static_cast(services[2]->get())->number(), 4); + EXPECT_EQ(static_cast(services[3]->get())->number(), 5); + EXPECT_EQ(static_cast(services[4]->get())->number(), 6); } diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp index 278db98..9bf694b 100644 --- a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -5,7 +5,8 @@ #include "../../Helpers/Classes/CirularDependency.hpp" #include "../../Helpers/Classes/Inherit.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" +#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceCollection.hpp" @@ -30,10 +31,12 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstance) ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; - const auto instance = creator.createInstance(descriptor, false); + const auto instance = resolver.createInstance(); EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); @@ -41,77 +44,404 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstance) EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); } -TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceAlias) +TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstance) { + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instance = resolver.createInstance(); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass4)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createOneInstance(); + + EXPECT_EQ(instances.size(), 1); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstance) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createOneInstance(); + + EXPECT_EQ(instances.size(), 1); + EXPECT_FALSE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass4)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstances) +{ + ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createAllInstances(); + + EXPECT_EQ(instances.size(), 1); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstances) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createAllInstances(); + + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstances) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + sb::di::details::containers::ServiceInstanceList instances{ + descriptors.last().getImplementationFactory().createInstance(mock, false)}; + resolver.createRestInstances(instances); + + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceInPlace) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instance = resolver.createInstanceInPlace(); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); +} - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); +TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstanceInPlace) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); - TestInheritClass5 test; - const sb::di::details::services::ExternalService external{&test}; + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; - const auto instance = creator.createInstanceAlias(typeid(TestInheritClass3), &external); + const auto instance = resolver.createInstanceInPlace(); EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass4)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstanceInPlace) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createOneInstanceInPlace(); + + EXPECT_EQ(instances.size(), 1); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); } -TEST_F(ServiceInstanceResolverTest, ShouldFailForNullProvider) +TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstanceInPlace) { ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; - EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::NullPointerException); + const auto instances = resolver.createOneInstanceInPlace(); + + EXPECT_EQ(instances.size(), 1); + EXPECT_FALSE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass4)); } -TEST_F(ServiceInstanceResolverTest, ShouldFailForInvalidInstance) +TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstancesInPlace) { ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; creator.setServiceProvider(mock); + const sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(nullptr); + const auto instances = resolver.createAllInstancesInPlace(); - EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::InvalidServiceException); + EXPECT_EQ(instances.size(), 1); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); } -TEST_F(ServiceInstanceResolverTest, ShouldFailForCirculatDependency) +TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstancesInPlace) { ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + const auto instances = resolver.createAllInstancesInPlace(); + + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); +} - EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyA)})) - .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); - creator.createInstance(descriptor, false); - return nullptr; - })); +TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstancesInPlace) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeSingleton()}; + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); + descriptors.add(sb::di::ServiceDescriber::describeSingleton()); - EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(CircularDependencyB)})) - .WillOnce(testing::Invoke([&](sb::di::TypeId typeId) { - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); - creator.createInstance(descriptor, false); - return nullptr; - })); + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + sb::di::details::containers::ServiceInstanceList instances{ + descriptors.last().getImplementationFactory().createInstance(mock, true)}; + resolver.createRestInstancesInPlace(instances); - EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::CircularDependencyException); + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); } -TEST_F(ServiceInstanceResolverTest, ShouldFailCreateInstanceAlias) +TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) { + ServiceProviderMock mock; sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeAlias()}; + descriptors.add(sb::di::ServiceDescriber::describeAlias()); + descriptors.add(sb::di::ServiceDescriber::describeAlias()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + TestInheritClass6 test; + const sb::di::details::services::ExternalService external(&test); + const auto instance = resolver.createAlias(external); + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance->isValid()); + EXPECT_TRUE(instance->get()); + EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass5)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateOneAlias) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeAlias()}; + descriptors.add(sb::di::ServiceDescriber::describeAlias()); + descriptors.add(sb::di::ServiceDescriber::describeAlias()); + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + TestInheritClass6 test; + const sb::di::details::services::ExternalService external(&test); + const auto instances = resolver.createOneAlias(external); + + EXPECT_EQ(instances.size(), 1); + EXPECT_FALSE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass5)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateAllAliases) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeAlias()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + TestInheritClass3 test3; + TestInheritClass4 test4; + TestInheritClass5 test5; + sb::di::details::containers::ServiceInstanceList externals{ + std::make_unique>(&test3)}; + externals.add(std::make_unique>(&test4)); + externals.add(std::make_unique>(&test5)); + + const auto instances = resolver.createAllAliases(externals.getInnerList()); + + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass2)); +} + +TEST_F(ServiceInstanceResolverTest, ShouldCreateRestAliases) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + sb::di::details::containers::ServiceDescriptorList descriptors{ + sb::di::ServiceDescriber::describeAlias()}; + + const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; + + TestInheritClass3 test3; + TestInheritClass4 test4; + TestInheritClass5 test5; + sb::di::details::containers::ServiceInstanceList externals{ + std::make_unique>(&test3)}; + externals.add(std::make_unique>(&test4)); + externals.add(std::make_unique>(&test5)); - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + sb::di::details::containers::ServiceInstanceList instances{ + std::make_unique>(&test5)}; - TestInheritClass5 *test = nullptr; - const sb::di::details::services::ExternalService external{test}; + auto &_ = resolver.createRestAliases(externals.getInnerList(), instances); - EXPECT_THROW(creator.createInstanceAlias(typeid(TestInheritClass3), &external), sb::di::InvalidServiceException); + EXPECT_EQ(instances.size(), 3); + EXPECT_TRUE(instances.isSealed()); + EXPECT_TRUE(instances.getInnerList()[0]->isValid()); + EXPECT_TRUE(instances.getInnerList()[0]->get()); + EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[1]->isValid()); + EXPECT_TRUE(instances.getInnerList()[1]->get()); + EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[2]->isValid()); + EXPECT_TRUE(instances.getInnerList()[2]->get()); + EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass2)); } From 8b6aa8671be86ebad57fa94ed329a56c701b69b0 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 31 Jan 2024 19:48:59 +0100 Subject: [PATCH 29/45] add support for multiple inheritance --- .../Containers/Impl/ServiceInstanceList.hpp | 18 +++---- .../Containers/Impl/ServiceInstancesMap.hpp | 2 +- .../Containers/ServiceInstanceList.hpp | 20 ++++---- .../Containers/ServiceInstancesMap.hpp | 4 +- .../Core/Impl/ServiceInstanceCreator.hpp | 17 ++++--- .../Core/Impl/ServiceInstanceProvider.hpp | 50 +++++++++++++++---- .../Core/Impl/ServiceInstancesResolver.hpp | 21 ++++---- .../Details/Core/ServiceInstanceCreator.hpp | 4 +- .../Details/Core/ServiceInstanceProvider.hpp | 20 +++++--- .../Details/Core/ServiceInstancesResolver.hpp | 16 +++--- .../Factories/ExternalServiceFactory.hpp | 4 +- .../DI/Details/Factories/ServiceFactory.hpp | 8 +-- .../Details/Factories/ServiceFcnFactory.hpp | 4 +- .../Details/Factories/VoidServiceFactory.hpp | 4 +- .../DI/Details/Services/AliasService.hpp | 4 +- .../DI/Details/Services/ExternalService.hpp | 4 +- .../DI/Details/Services/InPlaceService.hpp | 4 +- .../DI/Details/Services/UniquePtrService.hpp | 4 +- .../SevenBit/DI/Details/Utils/CastOffset.hpp | 19 +++++++ Include/SevenBit/DI/Details/Utils/Check.hpp | 6 +-- .../SevenBit/DI/Details/Utils/Impl/Check.hpp | 4 +- .../DI/Details/Utils/Impl/Require.hpp | 8 +-- Include/SevenBit/DI/Details/Utils/Require.hpp | 10 ++-- Include/SevenBit/DI/IServiceFactory.hpp | 4 +- .../SevenBit/DI/IServiceInstanceProvider.hpp | 18 +++---- .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 7 ++- Include/SevenBit/DI/ServiceDescriber.hpp | 13 +++-- Include/SevenBit/DI/ServiceDescriptor.hpp | 5 +- ...erviceInstance.hpp => ServiceInstance.hpp} | 21 +++++--- Include/SevenBit/DI/ServiceProvider.hpp | 4 +- .../Mocks/ServiceInstanceProviderMock.hpp | 16 +++--- .../Containers/ServiceInstanceListTest.cpp | 26 +++++----- .../Containers/ServiceInstancesMapTest.cpp | 14 +++--- .../Unit/Core/ServiceInstanceCreatorTest.cpp | 8 +-- Tests/Unit/Factories/ServiceFactoryTest.cpp | 8 +-- .../Unit/Factories/ServiceFcnFactoryTest.cpp | 8 +-- .../Unit/Helpers/ServiceParamProviderTest.cpp | 8 +-- Tests/Unit/ServiceDescriptorTest.cpp | 2 +- 38 files changed, 245 insertions(+), 172 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Utils/CastOffset.hpp rename Include/SevenBit/DI/{IServiceInstance.hpp => ServiceInstance.hpp} (88%) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp index 63a5c8c..56015cd 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp @@ -4,30 +4,30 @@ #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::containers { INLINE ServiceInstanceList::ServiceInstanceList(const size_t size) : _oneOrList(size) {} - INLINE ServiceInstanceList::ServiceInstanceList(IServiceInstance::Ptr instance) + INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance::Ptr instance) : _oneOrList(details::utils::Require::validInstanceAndGet(std::move(instance))) { } - INLINE void ServiceInstanceList::add(IServiceInstance::Ptr &&service) + INLINE void ServiceInstanceList::add(ServiceInstance::Ptr &&service) { _oneOrList.add(details::utils::Require::validInstanceAndGet(std::move(service))); } - INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } - INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } + INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } + INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } - INLINE IServiceInstance::Ptr &ServiceInstanceList::first() { return _oneOrList.first(); } - INLINE const IServiceInstance::Ptr &ServiceInstanceList::first() const { return _oneOrList.first(); } + INLINE ServiceInstance::Ptr &ServiceInstanceList::first() { return _oneOrList.first(); } + INLINE const ServiceInstance::Ptr &ServiceInstanceList::first() const { return _oneOrList.first(); } - INLINE IServiceInstance::Ptr &ServiceInstanceList::last() { return _oneOrList.last(); } - INLINE const IServiceInstance::Ptr &ServiceInstanceList::last() const { return _oneOrList.last(); } + INLINE ServiceInstance::Ptr &ServiceInstanceList::last() { return _oneOrList.last(); } + INLINE const ServiceInstance::Ptr &ServiceInstanceList::last() const { return _oneOrList.last(); } INLINE size_t ServiceInstanceList::size() const { return _oneOrList.size(); } diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index 1547355..2401456 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -11,7 +11,7 @@ namespace sb::di::details::containers { } - INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, IServiceInstance::Ptr instance) + INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, ServiceInstance::Ptr instance) { return insert(serviceTypeId, ServiceInstanceList{std::move(instance)}); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index c8b0e86..b8d5124 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -4,18 +4,18 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/OneOrList.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::containers { class EXPORT ServiceInstanceList { - OneOrList _oneOrList; + OneOrList _oneOrList; bool _sealed = false; public: - explicit ServiceInstanceList(IServiceInstance::Ptr instance); + explicit ServiceInstanceList(ServiceInstance::Ptr instance); explicit ServiceInstanceList(size_t size); ServiceInstanceList(const ServiceInstanceList &) = delete; @@ -24,19 +24,19 @@ namespace sb::di::details::containers ServiceInstanceList &operator=(const ServiceInstanceList &) = delete; ServiceInstanceList &operator=(ServiceInstanceList &&) = default; - void add(IServiceInstance::Ptr &&service); + void add(ServiceInstance::Ptr &&service); [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } [[nodiscard]] auto end() const { return _oneOrList.getAsList().end(); } - OneOrList &getInnerList(); - [[nodiscard]] const OneOrList &getInnerList() const; + OneOrList &getInnerList(); + [[nodiscard]] const OneOrList &getInnerList() const; - IServiceInstance::Ptr &first(); - [[nodiscard]] const IServiceInstance::Ptr &first() const; + ServiceInstance::Ptr &first(); + [[nodiscard]] const ServiceInstance::Ptr &first() const; - IServiceInstance::Ptr &last(); - [[nodiscard]] const IServiceInstance::Ptr &last() const; + ServiceInstance::Ptr &last(); + [[nodiscard]] const ServiceInstance::Ptr &last() const; [[nodiscard]] size_t size() const; diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp index b515d75..34c6fe8 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp @@ -6,7 +6,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::containers @@ -27,7 +27,7 @@ namespace sb::di::details::containers ServiceInstancesMap &operator=(const ServiceInstancesMap &) = delete; - ServiceInstanceList &insert(TypeId serviceTypeId, IServiceInstance::Ptr instance); + ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstance::Ptr instance); ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstanceList instances); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 5dd0288..9a03da0 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -15,19 +15,24 @@ namespace sb::di::details::core _serviceProvider = &serviceProvider; } - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) + INLINE ServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) { auto &provider = *utils::Require::notNullAndGet(_serviceProvider); auto &factory = descriptor.getImplementationFactory(); auto _ = _guard(descriptor.getImplementationTypeId()); - return utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); + auto instance = utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); + instance->addGetOffset(descriptor.getCastOffset()); + return std::move(instance); } - INLINE IServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(TypeId serviceTypeId, - const IServiceInstance *instance) + INLINE ServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(const ServiceDescriptor &descriptor, + const ServiceInstance *instance) { utils::Require::validInstance(instance); - return std::make_unique(instance->get(), serviceTypeId); + auto aliasInstance = + std::make_unique(instance->getAs(), descriptor.getImplementationTypeId()); + aliasInstance->addGetOffset(descriptor.getCastOffset()); + return std::move(aliasInstance); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index bdaf8b5..188c1bc 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -7,7 +7,7 @@ #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" #include "SevenBit/DI/ServiceProvider.hpp" @@ -33,7 +33,7 @@ namespace sb::di::details::core return std::make_unique(_root, _options); } - INLINE const IServiceInstance &ServiceInstanceProvider::getInstance(const TypeId serviceTypeId) + INLINE const ServiceInstance &ServiceInstanceProvider::getInstance(const TypeId serviceTypeId) { if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::instanceValidity(instance)) { @@ -43,7 +43,7 @@ namespace sb::di::details::core "Service was not registered or was registered as transient instance"}; } - INLINE const IServiceInstance *ServiceInstanceProvider::tryGetInstance(const TypeId serviceTypeId) + INLINE const ServiceInstance *ServiceInstanceProvider::tryGetInstance(const TypeId serviceTypeId) { auto instances = findRegisteredInstances(serviceTypeId); if (!instances) @@ -54,7 +54,7 @@ namespace sb::di::details::core return instances ? instances->last().get() : nullptr; } - INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) + INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { auto instances = findRegisteredInstances(serviceTypeId); if (!instances) @@ -70,7 +70,7 @@ namespace sb::di::details::core return instances ? &instances->getInnerList() : nullptr; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) + INLINE ServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) { if (auto instance = tryCreateInstance(serviceTypeId); utils::Check::instanceValidity(instance)) { @@ -80,34 +80,38 @@ namespace sb::di::details::core "Service was not registered or was registered as singleton/scoped instance"}; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) + INLINE ServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true)) { if (descriptors->isAlias()) { - return tryCreateInstance(descriptors->last().getImplementationTypeId()); + auto alias = tryCreateInstance(descriptors->last().getImplementationTypeId()); + tryAddOffset(alias.get(), descriptors->last()); + return alias; } return makeResolver(*descriptors).createInstance(); } return nullptr; } - INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( + INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true)) { if (descriptors->isAlias()) { - return tryCreateInstances(descriptors->last().getImplementationTypeId()); + auto aliases = tryCreateInstances(descriptors->last().getImplementationTypeId()); + tryAddOffset(aliases, descriptors->last()); + return std::move(aliases); } return std::move(makeResolver(*descriptors).createAllInstances().getInnerList()); } return std::nullopt; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) + INLINE ServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) { if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) { @@ -118,7 +122,7 @@ namespace sb::di::details::core "registered as singleton/scoped instance"}; } - INLINE IServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) + INLINE ServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true); descriptors && !descriptors->isAlias() && descriptors->last().getImplementationTypeId() == serviceTypeId) @@ -215,4 +219,28 @@ namespace sb::di::details::core auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; return ServiceInstancesResolver{creator, descriptors}; } + + INLINE void ServiceInstanceProvider::tryAddOffset(ServiceInstance *instance, const ServiceDescriptor &descriptor) + { + if (instance && descriptor.getCastOffset()) + { + instance->addGetOffset(descriptor.getCastOffset()); + } + } + + INLINE void ServiceInstanceProvider::tryAddOffset(std::optional> &instances, + const ServiceDescriptor &descriptor) + { + if (instances && descriptor.getCastOffset()) + { + if (instances->size() == 1) + { + return tryAddOffset(instances->first().get(), descriptor); + } + for (auto &instance : instances->getAsList()) + { + tryAddOffset(instance.get(), descriptor); + } + } + } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index a139544..eaa77e2 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -15,7 +15,7 @@ namespace sb::di::details::core { } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance() const { return createInstance(false); } + INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstance() const { return createInstance(false); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance() const { @@ -33,10 +33,7 @@ namespace sb::di::details::core return createRestInstances(instances, false); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() const - { - return createInstance(true); - } + INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() const { return createInstance(true); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstanceInPlace() const { @@ -54,26 +51,26 @@ namespace sb::di::details::core return createRestInstances(instances, true); } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance &original) const + INLINE ServiceInstance::Ptr ServiceInstancesResolver::createAlias(const ServiceInstance &original) const { return createAlias(&original); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneAlias( - const IServiceInstance &original) const + const ServiceInstance &original) const { return containers::ServiceInstanceList{createAlias(&original)}; } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( - const OneOrList &originals) const + const OneOrList &originals) const { containers::ServiceInstanceList aliases{createAlias(originals.last().get())}; return std::move(createRestAliases(originals, aliases)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( - const OneOrList &originals, containers::ServiceInstanceList &instances) const + const OneOrList &originals, containers::ServiceInstanceList &instances) const { if (originals.size() > 1) { @@ -92,7 +89,7 @@ namespace sb::di::details::core return instances; } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const + INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const { return _creator.createInstance(_descriptors.last(), inPlaceRequest); } @@ -132,9 +129,9 @@ namespace sb::di::details::core return instances; } - INLINE IServiceInstance::Ptr ServiceInstancesResolver::createAlias(const IServiceInstance *original) const + INLINE ServiceInstance::Ptr ServiceInstancesResolver::createAlias(const ServiceInstance *original) const { - return _creator.createInstanceAlias(_descriptors.last().getImplementationTypeId(), original); + return _creator.createInstanceAlias(_descriptors.last(), original); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index f8ff995..e117224 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -15,9 +15,9 @@ namespace sb::di::details::core public: void setServiceProvider(ServiceProvider &serviceProvider); - IServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + ServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); - IServiceInstance::Ptr createInstanceAlias(TypeId serviceTypeId, const IServiceInstance *instance); + ServiceInstance::Ptr createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index f227e6f..4e9ed06 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -43,16 +43,16 @@ namespace sb::di::details::core [[nodiscard]] IServiceInstanceProvider::Ptr createScope() const override; - const IServiceInstance &getInstance(TypeId serviceTypeId) override; - const IServiceInstance *tryGetInstance(TypeId serviceTypeId) override; - const OneOrList *tryGetInstances(TypeId serviceTypeId) override; + const ServiceInstance &getInstance(TypeId serviceTypeId) override; + const ServiceInstance *tryGetInstance(TypeId serviceTypeId) override; + const OneOrList *tryGetInstances(TypeId serviceTypeId) override; - IServiceInstance::Ptr createInstance(TypeId serviceTypeId) override; - IServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) override; - std::optional> tryCreateInstances(TypeId serviceTypeId) override; + ServiceInstance::Ptr createInstance(TypeId serviceTypeId) override; + ServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) override; + std::optional> tryCreateInstances(TypeId serviceTypeId) override; - IServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) override; - IServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) override; + ServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) override; + ServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) override; void clear(); @@ -72,6 +72,10 @@ namespace sb::di::details::core containers::ServiceInstanceList &instances); ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); + + void tryAddOffset(ServiceInstance *instance, const ServiceDescriptor &descriptor); + void tryAddOffset(std::optional> &instances, + const ServiceDescriptor &descriptor); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index bbd5c10..ab88842 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -16,31 +16,31 @@ namespace sb::di::details::core public: ServiceInstancesResolver(ServiceInstanceCreator &creator, const containers::ServiceDescriptorList &descriptors); - [[nodiscard]] IServiceInstance::Ptr createInstance() const; + [[nodiscard]] ServiceInstance::Ptr createInstance() const; [[nodiscard]] containers::ServiceInstanceList createOneInstance() const; [[nodiscard]] containers::ServiceInstanceList createAllInstances() const; containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances) const; - [[nodiscard]] IServiceInstance::Ptr createInstanceInPlace() const; + [[nodiscard]] ServiceInstance::Ptr createInstanceInPlace() const; [[nodiscard]] containers::ServiceInstanceList createOneInstanceInPlace() const; [[nodiscard]] containers::ServiceInstanceList createAllInstancesInPlace() const; containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; - [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance &original) const; - [[nodiscard]] containers::ServiceInstanceList createOneAlias(const IServiceInstance &original) const; + [[nodiscard]] ServiceInstance::Ptr createAlias(const ServiceInstance &original) const; + [[nodiscard]] containers::ServiceInstanceList createOneAlias(const ServiceInstance &original) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( - const OneOrList &originals) const; + const OneOrList &originals) const; [[nodiscard]] containers::ServiceInstanceList &createRestAliases( - const OneOrList &originals, containers::ServiceInstanceList &instances) const; + const OneOrList &originals, containers::ServiceInstanceList &instances) const; private: - [[nodiscard]] IServiceInstance::Ptr createInstance(bool inPlaceRequest) const; + [[nodiscard]] ServiceInstance::Ptr createInstance(bool inPlaceRequest) const; [[nodiscard]] containers::ServiceInstanceList createOneInstance(bool inPlaceRequest) const; [[nodiscard]] containers::ServiceInstanceList createAllInstances(bool inPlaceRequest) const; containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, bool inPlaceRequest) const; - [[nodiscard]] IServiceInstance::Ptr createAlias(const IServiceInstance *original) const; + [[nodiscard]] ServiceInstance::Ptr createAlias(const ServiceInstance *original) const; }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp index 7529ddc..3fbcbb4 100644 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp @@ -6,7 +6,7 @@ #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -21,7 +21,7 @@ namespace sb::di::details::factories [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { return std::make_unique>(_service); } diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp index e1959ff..640ca2e 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp @@ -9,7 +9,7 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::factories { @@ -18,7 +18,7 @@ namespace sb::di::details::factories using ServiceCtorInvoker = helpers::ServiceCtorInvoker; struct InPlaceCreator { - template IServiceInstance::Ptr operator()(Args &&...params) + template ServiceInstance::Ptr operator()(Args &&...params) { return std::make_unique>(std::forward(params)...); } @@ -26,7 +26,7 @@ namespace sb::di::details::factories struct UniqueCreator { - template IServiceInstance::Ptr operator()(Args &&...params) + template ServiceInstance::Ptr operator()(Args &&...params) { auto servicePtr = std::make_unique(std::forward(params)...); return std::make_unique>(std::move(servicePtr)); @@ -36,7 +36,7 @@ namespace sb::di::details::factories public: [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceCtorInvoker invoker{serviceProvider}; if (inPlaceRequest) diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index c4ebf16..7758cb0 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -11,7 +11,7 @@ #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -35,7 +35,7 @@ namespace sb::di::details::factories [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; if constexpr (utils::IsUniquePtrV) diff --git a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp index bc1a03a..d413826 100644 --- a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp @@ -5,7 +5,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -16,7 +16,7 @@ namespace sb::di::details::factories public: [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { return nullptr; } diff --git a/Include/SevenBit/DI/Details/Services/AliasService.hpp b/Include/SevenBit/DI/Details/Services/AliasService.hpp index f108cfb..b309cd8 100644 --- a/Include/SevenBit/DI/Details/Services/AliasService.hpp +++ b/Include/SevenBit/DI/Details/Services/AliasService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::services { - class AliasService final : public IServiceInstance + class AliasService final : public ServiceInstance { void *_service = nullptr; TypeId _serviceTypeId; diff --git a/Include/SevenBit/DI/Details/Services/ExternalService.hpp b/Include/SevenBit/DI/Details/Services/ExternalService.hpp index f97a8d4..4997a40 100644 --- a/Include/SevenBit/DI/Details/Services/ExternalService.hpp +++ b/Include/SevenBit/DI/Details/Services/ExternalService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::services { - template class ExternalService final : public IServiceInstance + template class ExternalService final : public ServiceInstance { T *_service = nullptr; diff --git a/Include/SevenBit/DI/Details/Services/InPlaceService.hpp b/Include/SevenBit/DI/Details/Services/InPlaceService.hpp index 6c48fa0..8c80714 100644 --- a/Include/SevenBit/DI/Details/Services/InPlaceService.hpp +++ b/Include/SevenBit/DI/Details/Services/InPlaceService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::services { - template class InPlaceService final : public IServiceInstance + template class InPlaceService final : public ServiceInstance { T _service; diff --git a/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp b/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp index 94c60c4..ba7b35c 100644 --- a/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp +++ b/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp @@ -4,11 +4,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::services { - template class UniquePtrService final : public IServiceInstance + template class UniquePtrService final : public ServiceInstance { std::unique_ptr _service; diff --git a/Include/SevenBit/DI/Details/Utils/CastOffset.hpp b/Include/SevenBit/DI/Details/Utils/CastOffset.hpp new file mode 100644 index 0000000..2dc16d3 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/CastOffset.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + template struct CastOffset + { + static constexpr int get() + { + auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); + TService *service = implementation; + return reinterpret_cast(service) - reinterpret_cast(implementation); + }; + }; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 8e1fc7d..28b1d47 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -3,7 +3,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { @@ -20,9 +20,9 @@ namespace sb::di::details::utils return std::is_enum_v && value >= 0 && value < TEnum::Count; } - static bool instanceValidity(const IServiceInstance::Ptr &instance); + static bool instanceValidity(const ServiceInstance::Ptr &instance); - static bool instanceValidity(const IServiceInstance *instance); + static bool instanceValidity(const ServiceInstance *instance); }; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp index 3bf6d15..58dec46 100644 --- a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp @@ -6,12 +6,12 @@ namespace sb::di::details::utils { - INLINE bool Check::instanceValidity(const IServiceInstance::Ptr &instance) + INLINE bool Check::instanceValidity(const ServiceInstance::Ptr &instance) { return instanceValidity(instance.get()); } - INLINE bool Check::instanceValidity(const IServiceInstance *instance) + INLINE bool Check::instanceValidity(const ServiceInstance *instance) { return notNull(instance) && instance->isValid(); } diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp index aad86a8..8f9732a 100644 --- a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp @@ -7,21 +7,21 @@ namespace sb::di::details::utils { - INLINE IServiceInstance::Ptr Require::validInstanceAndGet(IServiceInstance::Ptr &&instance) + INLINE ServiceInstance::Ptr Require::validInstanceAndGet(ServiceInstance::Ptr &&instance) { validInstance(instance.get()); return std::move(instance); } - INLINE IServiceInstance &Require::validInstanceAndGet(IServiceInstance *instance) + INLINE ServiceInstance &Require::validInstanceAndGet(ServiceInstance *instance) { validInstance(instance); return *instance; } - INLINE void Require::validInstance(const IServiceInstance::Ptr &instance) { validInstance(instance.get()); } + INLINE void Require::validInstance(const ServiceInstance::Ptr &instance) { validInstance(instance.get()); } - INLINE void Require::validInstance(const IServiceInstance *instance) + INLINE void Require::validInstance(const ServiceInstance *instance) { notNull(instance); if (!Check::instanceValidity(instance)) diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index 28d7fd5..f1895fe 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -6,7 +6,7 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { @@ -68,13 +68,13 @@ namespace sb::di::details::utils } } - static IServiceInstance::Ptr validInstanceAndGet(IServiceInstance::Ptr &&instance); + static ServiceInstance::Ptr validInstanceAndGet(ServiceInstance::Ptr &&instance); - static IServiceInstance &validInstanceAndGet(IServiceInstance *instance); + static ServiceInstance &validInstanceAndGet(ServiceInstance *instance); - static void validInstance(const IServiceInstance::Ptr &instance); + static void validInstance(const ServiceInstance::Ptr &instance); - static void validInstance(const IServiceInstance *instance); + static void validInstance(const ServiceInstance *instance); }; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/IServiceFactory.hpp b/Include/SevenBit/DI/IServiceFactory.hpp index 5df7418..af65ecf 100644 --- a/Include/SevenBit/DI/IServiceFactory.hpp +++ b/Include/SevenBit/DI/IServiceFactory.hpp @@ -4,7 +4,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di { @@ -23,7 +23,7 @@ namespace sb::di /** * @brief Create a service instance object */ - virtual IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, bool inPlaceRequest) const = 0; + virtual ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, bool inPlaceRequest) const = 0; virtual ~IServiceFactory() = default; }; diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index a8cf40f..3f08f18 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -5,7 +5,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/OneOrList.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" #include "SevenBit/DI/TypeId.hpp" @@ -39,51 +39,51 @@ namespace sb::di * @details If service was not registered or was registered as transient, method throws exception * @throws sb::di::ServiceNotFoundException */ - virtual const IServiceInstance &getInstance(TypeId serviceTypeId) = 0; + virtual const ServiceInstance &getInstance(TypeId serviceTypeId) = 0; /** * @brief Returns service instance pointer * @details If service was not registered or was registered as transient, method returns null */ - virtual const IServiceInstance *tryGetInstance(TypeId serviceTypeId) = 0; + virtual const ServiceInstance *tryGetInstance(TypeId serviceTypeId) = 0; /** * @brief Returns service instances * @details If service instance was not registered or was registered as transient, method returns null */ - virtual const OneOrList *tryGetInstances(TypeId serviceTypeId) = 0; + virtual const OneOrList *tryGetInstances(TypeId serviceTypeId) = 0; /** * @brief Creates service instance unique pointer, might throw exception * @details If service was not registered or was registered as scoped/singleton, method throw exception * @throws sb::di::ServiceNotFoundException */ - virtual IServiceInstance::Ptr createInstance(TypeId serviceTypeId) = 0; + virtual ServiceInstance::Ptr createInstance(TypeId serviceTypeId) = 0; /** * @brief Creates service instance unique pointer, might be null * @details If service was not registered or was registered as scoped/singleton, method returns null */ - virtual IServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) = 0; + virtual ServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) = 0; /** * @brief Creates service instances * @details If service was not registered or was registered as scoped/singleton, method returns null option */ - virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; + virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; /** * @brief Creates service instance in place, might throw exception * @details If service was not registered or was registered as scoped/singleton, method throws exception * @throws sb::di::ServiceNotFoundException */ - virtual IServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) = 0; + virtual ServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) = 0; /** * @brief Creates service instance in place * @details If service was not registered or was registered as scoped/singleton, method returns null */ - virtual IServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; + virtual ServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; virtual ~IServiceInstanceProvider() = default; }; diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index 75ebf07..f2f302e 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -8,9 +8,10 @@ namespace sb::di { INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const ServiceLifeTime lifeTime, - IServiceFactory::Ptr implementationFactory, bool isAlias) + IServiceFactory::Ptr implementationFactory, const int castOffset, + const bool isAlias) : _serviceTypeId(serviceTypeId), _lifeTime(lifeTime), _isAlias(isAlias), - _implementationFactory(std::move(implementationFactory)) + _implementationFactory(std::move(implementationFactory)), _castOffset(castOffset) { details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); @@ -30,6 +31,8 @@ namespace sb::di return *_implementationFactory; } + INLINE int ServiceDescriptor::getCastOffset() const { return _castOffset; } + INLINE bool ServiceDescriptor::isAlias() const { return _isAlias; } INLINE bool ServiceDescriptor::operator==(const ServiceDescriptor &descriptor) const diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index ec06f10..f14d788 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -9,6 +9,7 @@ #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" +#include "SevenBit/DI/Details/Utils/CastOffset.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" @@ -107,7 +108,8 @@ namespace sb::di details::utils::Assert::inheritance(); auto factory = std::make_unique>(); - return {typeid(TService), lifetime, std::move(factory)}; + return {typeid(TService), lifetime, std::move(factory), + details::utils::CastOffset::get()}; } /** @@ -161,7 +163,8 @@ namespace sb::di details::utils::Assert::inheritance(); auto factory = std::make_unique>(service); - return {typeid(TService), ServiceLifeTimes::Singleton, std::move(factory)}; + return {typeid(TService), ServiceLifeTimes::Singleton, std::move(factory), + details::utils::CastOffset::get()}; } /** @@ -348,7 +351,8 @@ namespace sb::di details::utils::Assert::factoryInheritance(); auto factory = std::make_unique(std::forward(factoryFcn)); - return {typeid(TRealService), lifetime, std::move(factory)}; + return {typeid(TRealService), lifetime, std::move(factory), + details::utils::CastOffset::get()}; } template static ServiceDescriptor describeAlias() @@ -357,7 +361,8 @@ namespace sb::di details::utils::Assert::aliasInheritance(); auto factory = std::make_unique>(); - return {typeid(TAlias), ServiceLifeTimes::Scoped, std::move(factory), true}; + return {typeid(TAlias), ServiceLifeTimes::Scoped, std::move(factory), + details::utils::CastOffset::get(), true}; } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index 785c236..cc1a6d2 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -16,6 +16,7 @@ namespace sb::di ServiceLifeTime _lifeTime; bool _isAlias; IServiceFactory::SPtr _implementationFactory; + int _castOffset; public: using Ptr = std::unique_ptr; @@ -26,7 +27,7 @@ namespace sb::di * @throws sb::di::NullPointerException */ ServiceDescriptor(TypeId serviceTypeId, ServiceLifeTime lifeTime, IServiceFactory::Ptr implementationFactory, - bool isAlias = false); + int castOffset = 0, bool isAlias = false); ServiceDescriptor(const ServiceDescriptor &other) = default; ServiceDescriptor(ServiceDescriptor &&) = default; @@ -54,6 +55,8 @@ namespace sb::di */ [[nodiscard]] const IServiceFactory &getImplementationFactory() const; + [[nodiscard]] int getCastOffset() const; + /** * @brief Check if service is alias */ diff --git a/Include/SevenBit/DI/IServiceInstance.hpp b/Include/SevenBit/DI/ServiceInstance.hpp similarity index 88% rename from Include/SevenBit/DI/IServiceInstance.hpp rename to Include/SevenBit/DI/ServiceInstance.hpp index 8e8a30e..571050d 100644 --- a/Include/SevenBit/DI/IServiceInstance.hpp +++ b/Include/SevenBit/DI/ServiceInstance.hpp @@ -8,10 +8,11 @@ namespace sb::di { - struct IServiceInstance + class ServiceInstance { - using Ptr = std::unique_ptr; + int _getOffset = 0; + public: /** * @brief Returns service pointer as void * */ @@ -44,6 +45,11 @@ namespace sb::di */ [[nodiscard]] virtual void *release() = 0; + public: + using Ptr = std::unique_ptr; + + void addGetOffset(const int offset) { _getOffset += offset; } + /** * @brief Get the TypeId of service * @details This method can be used to check if casting is safe @@ -77,7 +83,7 @@ namespace sb::di * T* service = instance->getAs(); * @endcode */ - template [[nodiscard]] T *getAs() const { return static_cast(get()); } + template [[nodiscard]] T *getAs() const { return static_cast(applyOffset(get())); } /** * @brief Releases service ownership as pointer T * @@ -88,7 +94,7 @@ namespace sb::di * T* service = instance->releaseAs(); * @endcode */ - template T *releaseAs() { return static_cast(release()); } + template T *releaseAs() { return static_cast(applyOffset(release())); } /** * @brief Moves out service as unique_ptr @@ -110,8 +116,11 @@ namespace sb::di * T service = instance->moveOutAs(); * @endcode */ - template T &&moveOutAs() { return std::move(*static_cast(getForMoveOut())); } + template T &&moveOutAs() { return std::move(*static_cast(applyOffset(getForMoveOut()))); } + + virtual ~ServiceInstance() = default; - virtual ~IServiceInstance() = default; + private: + void *applyOffset(void *ptr) const { return static_cast(ptr) + _getOffset; } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index dabd815..5092134 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -151,7 +151,7 @@ namespace sb::di if (auto instances = getInstanceProvider().tryGetInstances(typeid(TService))) { return mapValidInstances( - *instances, [](const IServiceInstance::Ptr &instance) { return instance->getAs(); }); + *instances, [](const ServiceInstance::Ptr &instance) { return instance->getAs(); }); } return {}; } @@ -233,7 +233,7 @@ namespace sb::di { if (auto instances = getInstanceProvider().tryCreateInstances(typeid(TService))) { - return mapValidInstances(*instances, [](const IServiceInstance::Ptr &instance) { + return mapValidInstances(*instances, [](const ServiceInstance::Ptr &instance) { return instance->moveOutAsUniquePtr(); }); } diff --git a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp index eab5ca2..2305988 100644 --- a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp +++ b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp @@ -9,14 +9,14 @@ struct ServiceInstanceProviderMock : public sb::di::IServiceInstanceProvider MOCK_METHOD((std::unique_ptr), createScope, (), (const override)); MOCK_METHOD((const sb::di::ServiceProviderOptions &), getOptions, (), (const override)); MOCK_METHOD((void), init, (sb::di::ServiceProvider &), (override)); - MOCK_METHOD((const sb::di::IServiceInstance *), tryGetInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((const sb::di::IServiceInstance &), getInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((const sb::di::OneOrList *), tryGetInstances, + MOCK_METHOD((const sb::di::ServiceInstance *), tryGetInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((const sb::di::ServiceInstance &), getInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((const sb::di::OneOrList *), tryGetInstances, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::IServiceInstance::Ptr), tryCreateInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::IServiceInstance::Ptr), createInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::IServiceInstance::Ptr), tryCreateInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::IServiceInstance::Ptr), createInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((std::optional>), tryCreateInstances, + MOCK_METHOD((sb::di::ServiceInstance::Ptr), tryCreateInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance::Ptr), createInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance::Ptr), tryCreateInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance::Ptr), createInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((std::optional>), tryCreateInstances, (sb::di::TypeId serviceTypeId), (override)); }; diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index 633b157..c8bbc41 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -7,7 +7,7 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" class ServiceInstanceListTest : public testing::Test { @@ -28,10 +28,10 @@ class ServiceInstanceListTest : public testing::Test TEST_F(ServiceInstanceListTest, ShouldAddServices) { TestClass1 test; - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::ExternalService{&test}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; list.add(std::move(instance2)); } @@ -45,7 +45,7 @@ TEST_F(ServiceInstanceListTest, ShouldFailAddNullService) TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) { auto act = [&]() { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::UniquePtrService{nullptr}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::UniquePtrService{nullptr}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; }; @@ -54,13 +54,13 @@ TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) TEST_F(ServiceInstanceListTest, ShouldReturnProperSize) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; EXPECT_EQ(list.size(), 1); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; list.add(std::move(instance2)); EXPECT_EQ(list.size(), 2); @@ -68,13 +68,13 @@ TEST_F(ServiceInstanceListTest, ShouldReturnProperSize) TEST_F(ServiceInstanceListTest, ShouldReturnEmpty) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; list.add(std::move(instance2)); EXPECT_FALSE(list.empty()); @@ -82,7 +82,7 @@ TEST_F(ServiceInstanceListTest, ShouldReturnEmpty) TEST_F(ServiceInstanceListTest, ShouldSeal) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; EXPECT_NO_THROW(list.seal()); @@ -91,14 +91,14 @@ TEST_F(ServiceInstanceListTest, ShouldSeal) TEST_F(ServiceInstanceListTest, ShouldGetFirst) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; const auto firstServicePtr = service.get(); sb::di::details::containers::ServiceInstanceList list{std::move(service)}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; list.add(std::move(instance2)); EXPECT_EQ(list.first().get(), firstServicePtr); @@ -106,13 +106,13 @@ TEST_F(ServiceInstanceListTest, ShouldGetFirst) TEST_F(ServiceInstanceListTest, ShouldGetLast) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; sb::di::details::containers::ServiceInstanceList list{std::move(service)}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; const auto lastServicePtr = instance2.get(); list.add(std::move(instance2)); diff --git a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp index b292b47..dd6067d 100644 --- a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp +++ b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp @@ -31,7 +31,7 @@ TEST_F(ServiceInstancesMapTest, ShouldInsert) sb::di::details::containers::ServiceInstancesMap map{false}; TestClass1 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; auto act = [&] { map.insert(typeid(TestClass1), std::move(instance)); }; EXPECT_NO_THROW(act()); @@ -42,9 +42,9 @@ TEST_F(ServiceInstancesMapTest, ShouldCheckEmpty) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); EXPECT_FALSE(map.empty()); @@ -55,9 +55,9 @@ TEST_F(ServiceInstancesMapTest, ShouldContainsList) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); EXPECT_TRUE(map.contains(typeid(TestInheritClass1))); @@ -69,9 +69,9 @@ TEST_F(ServiceInstancesMapTest, ShouldFindList) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); const auto list = map.findServices(typeid(TestInheritClass1)); diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp index fa2a7b4..23a010e 100644 --- a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -45,12 +45,12 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) { sb::di::details::core::ServiceInstanceCreator creator; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); TestInheritClass5 test; const sb::di::details::services::ExternalService external{&test}; - const auto instance = creator.createInstanceAlias(typeid(TestInheritClass3), &external); + const auto instance = creator.createInstanceAlias(descriptor, &external); EXPECT_TRUE(instance); EXPECT_TRUE(instance->isValid()); @@ -108,10 +108,10 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) { sb::di::details::core::ServiceInstanceCreator creator; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); TestInheritClass5 *test = nullptr; const sb::di::details::services::ExternalService external{test}; - EXPECT_THROW(creator.createInstanceAlias(typeid(TestInheritClass3), &external), sb::di::InvalidServiceException); + EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); } diff --git a/Tests/Unit/Factories/ServiceFactoryTest.cpp b/Tests/Unit/Factories/ServiceFactoryTest.cpp index 2b7dc9c..6be3b4b 100644 --- a/Tests/Unit/Factories/ServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFactoryTest.cpp @@ -241,7 +241,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec1Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -262,7 +262,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec2Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -284,7 +284,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec3Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -306,7 +306,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec4Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index 271b65e..1b6553d 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -266,7 +266,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec1Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -288,7 +288,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -312,7 +312,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec3Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -335,7 +335,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp index 65ff2a5..c577465 100644 --- a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp +++ b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp @@ -174,7 +174,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec1Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -191,7 +191,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec2Service) { ServiceProviderMock mock; auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -209,7 +209,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec3Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -228,7 +228,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec4Service) ServiceProviderMock mock; auto service = std::make_unique(); auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 6b6b1b7..5c5bacb 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -63,7 +63,7 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) auto factory = std::make_unique>(); const auto factoryPtr = factory.get(); const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory), true}; + std::move(factory), 0, true}; EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); From 63458a5337e64139c5fcefef04da517ddd9e6955 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Fri, 2 Feb 2024 18:07:12 +0100 Subject: [PATCH 30/45] add serviceInstance wrapper --- .../Containers/Impl/ServiceDescriptorList.hpp | 3 + .../Containers/Impl/ServiceInstanceList.hpp | 30 +++--- .../Containers/Impl/ServiceInstancesMap.hpp | 2 +- .../Containers/ServiceDescriptorList.hpp | 3 + .../Containers/ServiceInstanceList.hpp | 19 ++-- .../Containers/ServiceInstancesMap.hpp | 2 +- .../Core/Impl/ServiceInstanceCreator.hpp | 17 ++-- .../Core/Impl/ServiceInstanceProvider.hpp | 98 ++++++++----------- .../Core/Impl/ServiceInstancesResolver.hpp | 54 +++++----- .../Details/Core/ServiceInstanceCreator.hpp | 4 +- .../Details/Core/ServiceInstanceProvider.hpp | 19 ++-- .../Details/Core/ServiceInstancesResolver.hpp | 14 +-- .../Factories/ExternalServiceFactory.hpp | 6 +- .../DI/Details/Factories/ServiceFactory.hpp | 10 +- .../Details/Factories/ServiceFcnFactory.hpp | 6 +- .../Details/Factories/VoidServiceFactory.hpp | 6 +- .../DI/Details/Services/AliasService.hpp | 4 +- .../DI/Details/Services/ExternalService.hpp | 4 +- .../DI/Details/Services/InPlaceService.hpp | 4 +- .../DI/Details/Services/UniquePtrService.hpp | 4 +- Include/SevenBit/DI/Details/Utils/Cast.hpp | 25 +++++ .../SevenBit/DI/Details/Utils/CastOffset.hpp | 19 ---- Include/SevenBit/DI/Details/Utils/Check.hpp | 10 -- .../SevenBit/DI/Details/Utils/Impl/Check.hpp | 18 ---- .../DI/Details/Utils/Impl/Require.hpp | 32 ------ Include/SevenBit/DI/Details/Utils/Require.hpp | 13 --- Include/SevenBit/DI/IServiceFactory.hpp | 9 +- Include/SevenBit/DI/IServiceInstance.hpp | 69 +++++++++++++ .../SevenBit/DI/IServiceInstanceProvider.hpp | 14 +-- .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 30 +++--- Include/SevenBit/DI/Impl/ServiceInstance.hpp | 52 ++++++++++ Include/SevenBit/DI/OneOrList.hpp | 66 +++++++++++++ Include/SevenBit/DI/ServiceDescriber.hpp | 19 ++-- Include/SevenBit/DI/ServiceDescriptor.hpp | 22 ++--- Include/SevenBit/DI/ServiceInstance.hpp | 85 ++++++---------- Include/SevenBit/DI/ServiceProvider.hpp | 54 +++++----- Source/Source.cpp | 3 +- 37 files changed, 456 insertions(+), 393 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Utils/Cast.hpp delete mode 100644 Include/SevenBit/DI/Details/Utils/CastOffset.hpp delete mode 100644 Include/SevenBit/DI/Details/Utils/Impl/Check.hpp delete mode 100644 Include/SevenBit/DI/Details/Utils/Impl/Require.hpp create mode 100644 Include/SevenBit/DI/IServiceInstance.hpp create mode 100644 Include/SevenBit/DI/Impl/ServiceInstance.hpp diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp index 7a2b6d0..3775828 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp @@ -26,6 +26,9 @@ namespace sb::di::details::containers _oneOrList.add(std::move(descriptor)); } + INLINE OneOrList &ServiceDescriptorList::getInnerList() { return _oneOrList; } + INLINE const OneOrList &ServiceDescriptorList::getInnerList() const { return _oneOrList; } + INLINE const ServiceDescriptor &ServiceDescriptorList::first() const { return _oneOrList.first(); } INLINE const ServiceDescriptor &ServiceDescriptorList::last() const { return _oneOrList.last(); } diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp index 56015cd..a1778ec 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp @@ -10,24 +10,28 @@ namespace sb::di::details::containers { INLINE ServiceInstanceList::ServiceInstanceList(const size_t size) : _oneOrList(size) {} - INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance::Ptr instance) - : _oneOrList(details::utils::Require::validInstanceAndGet(std::move(instance))) - { - } + INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance instance) : _oneOrList(std::move(instance)) {} - INLINE void ServiceInstanceList::add(ServiceInstance::Ptr &&service) + INLINE void ServiceInstanceList::add(ServiceInstance &&service) { - _oneOrList.add(details::utils::Require::validInstanceAndGet(std::move(service))); + if (const auto single = _oneOrList.tryGetAsSingle(); single && !single->isValid()) + { + *single = std::move(service); + } + else + { + _oneOrList.add(std::move(service)); + } } - INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } - INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } + INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } + INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } - INLINE ServiceInstance::Ptr &ServiceInstanceList::first() { return _oneOrList.first(); } - INLINE const ServiceInstance::Ptr &ServiceInstanceList::first() const { return _oneOrList.first(); } + INLINE ServiceInstance &ServiceInstanceList::first() { return _oneOrList.first(); } + INLINE const ServiceInstance &ServiceInstanceList::first() const { return _oneOrList.first(); } - INLINE ServiceInstance::Ptr &ServiceInstanceList::last() { return _oneOrList.last(); } - INLINE const ServiceInstance::Ptr &ServiceInstanceList::last() const { return _oneOrList.last(); } + INLINE ServiceInstance &ServiceInstanceList::last() { return _oneOrList.last(); } + INLINE const ServiceInstance &ServiceInstanceList::last() const { return _oneOrList.last(); } INLINE size_t ServiceInstanceList::size() const { return _oneOrList.size(); } @@ -49,7 +53,7 @@ namespace sb::di::details::containers { if (const auto single = _oneOrList.tryGetAsSingle()) { - single->reset(); + single->clear(); } else { diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index 2401456..e5958b3 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -11,7 +11,7 @@ namespace sb::di::details::containers { } - INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, ServiceInstance::Ptr instance) + INLINE ServiceInstanceList &ServiceInstancesMap::insert(const TypeId serviceTypeId, ServiceInstance instance) { return insert(serviceTypeId, ServiceInstanceList{std::move(instance)}); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp index b46c562..f82f643 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp @@ -24,6 +24,9 @@ namespace sb::di::details::containers ServiceDescriptorList &operator=(const ServiceDescriptorList &) = delete; ServiceDescriptorList &operator=(ServiceDescriptorList &&) = default; + OneOrList &getInnerList(); + [[nodiscard]] const OneOrList &getInnerList() const; + void add(ServiceDescriptor &&descriptor); [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index b8d5124..334e78c 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -11,11 +11,12 @@ namespace sb::di::details::containers { class EXPORT ServiceInstanceList { - OneOrList _oneOrList; + OneOrList _oneOrList; bool _sealed = false; public: - explicit ServiceInstanceList(ServiceInstance::Ptr instance); + explicit ServiceInstanceList(); + explicit ServiceInstanceList(ServiceInstance instance); explicit ServiceInstanceList(size_t size); ServiceInstanceList(const ServiceInstanceList &) = delete; @@ -24,19 +25,19 @@ namespace sb::di::details::containers ServiceInstanceList &operator=(const ServiceInstanceList &) = delete; ServiceInstanceList &operator=(ServiceInstanceList &&) = default; - void add(ServiceInstance::Ptr &&service); + void add(ServiceInstance &&service); [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } [[nodiscard]] auto end() const { return _oneOrList.getAsList().end(); } - OneOrList &getInnerList(); - [[nodiscard]] const OneOrList &getInnerList() const; + OneOrList &getInnerList(); + [[nodiscard]] const OneOrList &getInnerList() const; - ServiceInstance::Ptr &first(); - [[nodiscard]] const ServiceInstance::Ptr &first() const; + ServiceInstance &first(); + [[nodiscard]] const ServiceInstance &first() const; - ServiceInstance::Ptr &last(); - [[nodiscard]] const ServiceInstance::Ptr &last() const; + ServiceInstance &last(); + [[nodiscard]] const ServiceInstance &last() const; [[nodiscard]] size_t size() const; diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp index 34c6fe8..1c5d15d 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp @@ -27,7 +27,7 @@ namespace sb::di::details::containers ServiceInstancesMap &operator=(const ServiceInstancesMap &) = delete; - ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstance::Ptr instance); + ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstance instance); ServiceInstanceList &insert(TypeId serviceTypeId, ServiceInstanceList instances); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 9a03da0..fa5f5b1 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -15,24 +15,21 @@ namespace sb::di::details::core _serviceProvider = &serviceProvider; } - INLINE ServiceInstance::Ptr ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, - const bool inPlaceRequest) + INLINE ServiceInstance ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, + const bool inPlaceRequest) { auto &provider = *utils::Require::notNullAndGet(_serviceProvider); auto &factory = descriptor.getImplementationFactory(); auto _ = _guard(descriptor.getImplementationTypeId()); - auto instance = utils::Require::validInstanceAndGet(factory.createInstance(provider, inPlaceRequest)); - instance->addGetOffset(descriptor.getCastOffset()); - return std::move(instance); + return ServiceInstance{factory.createInstance(provider, inPlaceRequest), descriptor.getCastOffset()}; } - INLINE ServiceInstance::Ptr ServiceInstanceCreator::createInstanceAlias(const ServiceDescriptor &descriptor, - const ServiceInstance *instance) + INLINE ServiceInstance ServiceInstanceCreator::createInstanceAlias(const ServiceDescriptor &descriptor, + const ServiceInstance *instance) { - utils::Require::validInstance(instance); + utils::Require::notNull(instance); auto aliasInstance = std::make_unique(instance->getAs(), descriptor.getImplementationTypeId()); - aliasInstance->addGetOffset(descriptor.getCastOffset()); - return std::move(aliasInstance); + return ServiceInstance{std::move(aliasInstance), descriptor.getCastOffset()}; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 188c1bc..88798ff 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -23,7 +23,7 @@ namespace sb::di::details::core { _instanceCreator.setServiceProvider(serviceProvider); auto external = std::make_unique>(&serviceProvider); - _scoped.insert(external->getTypeId(), std::move(external)).seal(); + _scoped.insert(external->getTypeId(), ServiceInstance{std::move(external)}).seal(); } INLINE const ServiceProviderOptions &ServiceInstanceProvider::getOptions() const { return _options; } @@ -35,7 +35,7 @@ namespace sb::di::details::core INLINE const ServiceInstance &ServiceInstanceProvider::getInstance(const TypeId serviceTypeId) { - if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::instanceValidity(instance)) + if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::notNull(instance)) { return *instance; } @@ -51,10 +51,10 @@ namespace sb::di::details::core const auto descriptors = findDescriptors(serviceTypeId, false); instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreate(*descriptors)) : nullptr; } - return instances ? instances->last().get() : nullptr; + return instances ? &instances->last() : nullptr; } - INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) + INLINE const OneOrList *ServiceInstanceProvider::tryGetInstances(const TypeId serviceTypeId) { auto instances = findRegisteredInstances(serviceTypeId); if (!instances) @@ -70,9 +70,9 @@ namespace sb::di::details::core return instances ? &instances->getInnerList() : nullptr; } - INLINE ServiceInstance::Ptr ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) + INLINE ServiceInstance ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) { - if (auto instance = tryCreateInstance(serviceTypeId); utils::Check::instanceValidity(instance)) + if (auto instance = tryCreateInstance(serviceTypeId); instance.isValid()) { return instance; } @@ -80,40 +80,30 @@ namespace sb::di::details::core "Service was not registered or was registered as singleton/scoped instance"}; } - INLINE ServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) + INLINE ServiceInstance ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true)) { - if (descriptors->isAlias()) - { - auto alias = tryCreateInstance(descriptors->last().getImplementationTypeId()); - tryAddOffset(alias.get(), descriptors->last()); - return alias; - } - return makeResolver(*descriptors).createInstance(); + return descriptors->isAlias() ? tryCreateAlias(descriptors->last()) + : makeResolver(*descriptors).createInstance(); } - return nullptr; + return ServiceInstance{}; } - INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( + INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true)) { - if (descriptors->isAlias()) - { - auto aliases = tryCreateInstances(descriptors->last().getImplementationTypeId()); - tryAddOffset(aliases, descriptors->last()); - return std::move(aliases); - } - return std::move(makeResolver(*descriptors).createAllInstances().getInnerList()); + return descriptors->isAlias() ? tryCreateAliases(descriptors->last()) + : std::move(makeResolver(*descriptors).createAllInstances().getInnerList()); } return std::nullopt; } - INLINE ServiceInstance::Ptr ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) + INLINE ServiceInstance ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) { - if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) + if (auto instance = tryCreateInstanceInPlace(serviceTypeId); instance.isValid()) { return instance; } @@ -122,14 +112,14 @@ namespace sb::di::details::core "registered as singleton/scoped instance"}; } - INLINE ServiceInstance::Ptr ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) + INLINE ServiceInstance ServiceInstanceProvider::tryCreateInstanceInPlace(const TypeId serviceTypeId) { if (const auto descriptors = findDescriptors(serviceTypeId, true); descriptors && !descriptors->isAlias() && descriptors->last().getImplementationTypeId() == serviceTypeId) { return makeResolver(*descriptors).createInstanceInPlace(); } - return nullptr; + return ServiceInstance{}; } INLINE void ServiceInstanceProvider::clear() { _scoped.clear(); } @@ -157,18 +147,18 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegisterAndGet( const containers::ServiceDescriptorList &descriptors, std::optional instances) { - if (!instances) + if (instances) { - return nullptr; - } - auto lifeTime = descriptors.getLifeTime(); - if (descriptors.isAlias()) - { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); - lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; + auto lifeTime = descriptors.getLifeTime(); + if (descriptors.isAlias()) + { + const auto originalTypeId = descriptors.last().getImplementationTypeId(); + lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; + } + auto &instancesMap = lifeTime.isSingleton() ? _root.getSingletons() : _scoped; + return &instancesMap.insert(descriptors.getServiceTypeId(), std::move(*instances)); } - auto &instancesMap = lifeTime.isSingleton() ? _root.getSingletons() : _scoped; - return &instancesMap.insert(descriptors.getServiceTypeId(), std::move(*instances)); + return nullptr; } INLINE std::optional ServiceInstanceProvider::tryCreate( @@ -213,34 +203,28 @@ namespace sb::di::details::core return &makeResolver(descriptors).createRestInstancesInPlace(instances); } - INLINE ServiceInstancesResolver - ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) + INLINE ServiceInstance ServiceInstanceProvider::tryCreateAlias(const ServiceDescriptor &descriptor) { - auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; - return ServiceInstancesResolver{creator, descriptors}; + auto alias = tryCreateInstance(descriptor.getImplementationTypeId()); + alias.addCastOffset(descriptor.getCastOffset()); + return alias; } - INLINE void ServiceInstanceProvider::tryAddOffset(ServiceInstance *instance, const ServiceDescriptor &descriptor) + INLINE std::optional> ServiceInstanceProvider::tryCreateAliases( + const ServiceDescriptor &descriptor) { - if (instance && descriptor.getCastOffset()) + auto aliases = tryCreateInstances(descriptor.getImplementationTypeId()); + if (aliases && descriptor.getCastOffset()) { - instance->addGetOffset(descriptor.getCastOffset()); + aliases->forEach([&](ServiceInstance &instance) { instance.addCastOffset(descriptor.getCastOffset()); }); } + return aliases; } - INLINE void ServiceInstanceProvider::tryAddOffset(std::optional> &instances, - const ServiceDescriptor &descriptor) + INLINE ServiceInstancesResolver + ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { - if (instances && descriptor.getCastOffset()) - { - if (instances->size() == 1) - { - return tryAddOffset(instances->first().get(), descriptor); - } - for (auto &instance : instances->getAsList()) - { - tryAddOffset(instance.get(), descriptor); - } - } + auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; + return ServiceInstancesResolver{creator, descriptors}; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index eaa77e2..3206a67 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -15,7 +16,7 @@ namespace sb::di::details::core { } - INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstance() const { return createInstance(false); } + INLINE ServiceInstance ServiceInstancesResolver::createInstance() const { return createInstance(false); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstance() const { @@ -33,7 +34,7 @@ namespace sb::di::details::core return createRestInstances(instances, false); } - INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstanceInPlace() const { return createInstance(true); } + INLINE ServiceInstance ServiceInstancesResolver::createInstanceInPlace() const { return createInstance(true); } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createOneInstanceInPlace() const { @@ -51,7 +52,7 @@ namespace sb::di::details::core return createRestInstances(instances, true); } - INLINE ServiceInstance::Ptr ServiceInstancesResolver::createAlias(const ServiceInstance &original) const + INLINE ServiceInstance ServiceInstancesResolver::createAlias(const ServiceInstance &original) const { return createAlias(&original); } @@ -63,33 +64,33 @@ namespace sb::di::details::core } INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( - const OneOrList &originals) const + const OneOrList &originals) const { - containers::ServiceInstanceList aliases{createAlias(originals.last().get())}; + containers::ServiceInstanceList aliases{createAlias(originals.last())}; return std::move(createRestAliases(originals, aliases)); } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( - const OneOrList &originals, containers::ServiceInstanceList &instances) const + const OneOrList &originals, containers::ServiceInstanceList &instances) const { - if (originals.size() > 1) + if (const auto size = originals.size(); size > 1) { - auto &list = originals.getAsList(); - instances.reserve(list.size()); - auto realFirst = createAlias(list.front().get()); - const auto end = --list.end(); - for (auto it = ++list.begin(); it != end; ++it) // skip first and last - { - instances.add(createAlias(it->get())); - } + instances.reserve(size); + auto realFirst = createAlias(originals.first()); + originals.forEach([&](const ServiceInstance &instance, const size_t index) { + if (index && index < size - 1) // skip first and last + { + instances.add(createAlias(instance)); + } + }); instances.add(std::move(realFirst)); - instances.first().swap(instances.last()); + std::swap(instances.first(), instances.last()); } instances.seal(); return instances; } - INLINE ServiceInstance::Ptr ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const + INLINE ServiceInstance ServiceInstancesResolver::createInstance(const bool inPlaceRequest) const { return _creator.createInstance(_descriptors.last(), inPlaceRequest); } @@ -113,23 +114,24 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( containers::ServiceInstanceList &instances, const bool inPlaceRequest) const { - if (_descriptors.size() > 1) + if (const auto size = _descriptors.size(); size > 1) { - instances.reserve(_descriptors.size()); + instances.reserve(size); auto realFirst = _creator.createInstance(_descriptors.first(), inPlaceRequest); - const auto end = --_descriptors.end(); - for (auto it = ++_descriptors.begin(); it != end; ++it) // skip first and last - { - instances.add(_creator.createInstance(*it, inPlaceRequest)); - } + _descriptors.getInnerList().forEach([&](const ServiceDescriptor &descriptor, const size_t index) { + if (index && index < size - 1) // skip first and last + { + instances.add(_creator.createInstance(descriptor, inPlaceRequest)); + } + }); instances.add(std::move(realFirst)); - instances.first().swap(instances.last()); + std::swap(instances.first(), instances.last()); } instances.seal(); return instances; } - INLINE ServiceInstance::Ptr ServiceInstancesResolver::createAlias(const ServiceInstance *original) const + INLINE ServiceInstance ServiceInstancesResolver::createAlias(const ServiceInstance *original) const { return _creator.createInstanceAlias(_descriptors.last(), original); } diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index e117224..ec0075c 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -15,9 +15,9 @@ namespace sb::di::details::core public: void setServiceProvider(ServiceProvider &serviceProvider); - ServiceInstance::Ptr createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); + ServiceInstance createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); - ServiceInstance::Ptr createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance); + ServiceInstance createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 4e9ed06..3b1f3ba 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -45,14 +45,14 @@ namespace sb::di::details::core const ServiceInstance &getInstance(TypeId serviceTypeId) override; const ServiceInstance *tryGetInstance(TypeId serviceTypeId) override; - const OneOrList *tryGetInstances(TypeId serviceTypeId) override; + const OneOrList *tryGetInstances(TypeId serviceTypeId) override; - ServiceInstance::Ptr createInstance(TypeId serviceTypeId) override; - ServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) override; - std::optional> tryCreateInstances(TypeId serviceTypeId) override; + ServiceInstance createInstance(TypeId serviceTypeId) override; + ServiceInstance tryCreateInstance(TypeId serviceTypeId) override; + std::optional> tryCreateInstances(TypeId serviceTypeId) override; - ServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) override; - ServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) override; + ServiceInstance createInstanceInPlace(TypeId serviceTypeId) override; + ServiceInstance tryCreateInstanceInPlace(TypeId serviceTypeId) override; void clear(); @@ -71,11 +71,10 @@ namespace sb::di::details::core containers::ServiceInstanceList *createRestAndGet(const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); - ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); + ServiceInstance tryCreateAlias(const ServiceDescriptor &descriptor); + std::optional> tryCreateAliases(const ServiceDescriptor &descriptor); - void tryAddOffset(ServiceInstance *instance, const ServiceDescriptor &descriptor); - void tryAddOffset(std::optional> &instances, - const ServiceDescriptor &descriptor); + ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp index ab88842..784e3d0 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp @@ -16,31 +16,31 @@ namespace sb::di::details::core public: ServiceInstancesResolver(ServiceInstanceCreator &creator, const containers::ServiceDescriptorList &descriptors); - [[nodiscard]] ServiceInstance::Ptr createInstance() const; + [[nodiscard]] ServiceInstance createInstance() const; [[nodiscard]] containers::ServiceInstanceList createOneInstance() const; [[nodiscard]] containers::ServiceInstanceList createAllInstances() const; containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances) const; - [[nodiscard]] ServiceInstance::Ptr createInstanceInPlace() const; + [[nodiscard]] ServiceInstance createInstanceInPlace() const; [[nodiscard]] containers::ServiceInstanceList createOneInstanceInPlace() const; [[nodiscard]] containers::ServiceInstanceList createAllInstancesInPlace() const; containers::ServiceInstanceList &createRestInstancesInPlace(containers::ServiceInstanceList &instances) const; - [[nodiscard]] ServiceInstance::Ptr createAlias(const ServiceInstance &original) const; + [[nodiscard]] ServiceInstance createAlias(const ServiceInstance &original) const; [[nodiscard]] containers::ServiceInstanceList createOneAlias(const ServiceInstance &original) const; [[nodiscard]] containers::ServiceInstanceList createAllAliases( - const OneOrList &originals) const; + const OneOrList &originals) const; [[nodiscard]] containers::ServiceInstanceList &createRestAliases( - const OneOrList &originals, containers::ServiceInstanceList &instances) const; + const OneOrList &originals, containers::ServiceInstanceList &instances) const; private: - [[nodiscard]] ServiceInstance::Ptr createInstance(bool inPlaceRequest) const; + [[nodiscard]] ServiceInstance createInstance(bool inPlaceRequest) const; [[nodiscard]] containers::ServiceInstanceList createOneInstance(bool inPlaceRequest) const; [[nodiscard]] containers::ServiceInstanceList createAllInstances(bool inPlaceRequest) const; containers::ServiceInstanceList &createRestInstances(containers::ServiceInstanceList &instances, bool inPlaceRequest) const; - [[nodiscard]] ServiceInstance::Ptr createAlias(const ServiceInstance *original) const; + [[nodiscard]] ServiceInstance createAlias(const ServiceInstance *original) const; }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp index 3fbcbb4..de7ac92 100644 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp @@ -6,7 +6,7 @@ #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -19,9 +19,7 @@ namespace sb::di::details::factories public: explicit ExternalServiceFactory(T *service) : _service{service} {} - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - - ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { return std::make_unique>(_service); } diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp index 640ca2e..8fda5aa 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp @@ -9,7 +9,7 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::factories { @@ -18,7 +18,7 @@ namespace sb::di::details::factories using ServiceCtorInvoker = helpers::ServiceCtorInvoker; struct InPlaceCreator { - template ServiceInstance::Ptr operator()(Args &&...params) + template IServiceInstance::Ptr operator()(Args &&...params) { return std::make_unique>(std::forward(params)...); } @@ -26,7 +26,7 @@ namespace sb::di::details::factories struct UniqueCreator { - template ServiceInstance::Ptr operator()(Args &&...params) + template IServiceInstance::Ptr operator()(Args &&...params) { auto servicePtr = std::make_unique(std::forward(params)...); return std::make_unique>(std::move(servicePtr)); @@ -34,9 +34,7 @@ namespace sb::di::details::factories }; public: - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - - ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceCtorInvoker invoker{serviceProvider}; if (inPlaceRequest) diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index 7758cb0..36349a9 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -11,7 +11,7 @@ #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -33,9 +33,7 @@ namespace sb::di::details::factories "Service factory return type must be std::unique_ptr or copyable/movable object"); } - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(ServiceType); } - - ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { ServiceFactoryInvoker invoker{_factoryFunction, serviceProvider}; if constexpr (utils::IsUniquePtrV) diff --git a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp index d413826..0eb3c68 100644 --- a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp @@ -5,7 +5,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories @@ -14,9 +14,7 @@ namespace sb::di::details::factories template class VoidServiceFactory final : public IServiceFactory { public: - [[nodiscard]] TypeId getServiceTypeId() const override { return typeid(T); } - - ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override + IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override { return nullptr; } diff --git a/Include/SevenBit/DI/Details/Services/AliasService.hpp b/Include/SevenBit/DI/Details/Services/AliasService.hpp index b309cd8..f108cfb 100644 --- a/Include/SevenBit/DI/Details/Services/AliasService.hpp +++ b/Include/SevenBit/DI/Details/Services/AliasService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::services { - class AliasService final : public ServiceInstance + class AliasService final : public IServiceInstance { void *_service = nullptr; TypeId _serviceTypeId; diff --git a/Include/SevenBit/DI/Details/Services/ExternalService.hpp b/Include/SevenBit/DI/Details/Services/ExternalService.hpp index 4997a40..f97a8d4 100644 --- a/Include/SevenBit/DI/Details/Services/ExternalService.hpp +++ b/Include/SevenBit/DI/Details/Services/ExternalService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::services { - template class ExternalService final : public ServiceInstance + template class ExternalService final : public IServiceInstance { T *_service = nullptr; diff --git a/Include/SevenBit/DI/Details/Services/InPlaceService.hpp b/Include/SevenBit/DI/Details/Services/InPlaceService.hpp index 8c80714..6c48fa0 100644 --- a/Include/SevenBit/DI/Details/Services/InPlaceService.hpp +++ b/Include/SevenBit/DI/Details/Services/InPlaceService.hpp @@ -5,11 +5,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::services { - template class InPlaceService final : public ServiceInstance + template class InPlaceService final : public IServiceInstance { T _service; diff --git a/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp b/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp index ba7b35c..94c60c4 100644 --- a/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp +++ b/Include/SevenBit/DI/Details/Services/UniquePtrService.hpp @@ -4,11 +4,11 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::services { - template class UniquePtrService final : public ServiceInstance + template class UniquePtrService final : public IServiceInstance { std::unique_ptr _service; diff --git a/Include/SevenBit/DI/Details/Utils/Cast.hpp b/Include/SevenBit/DI/Details/Utils/Cast.hpp new file mode 100644 index 0000000..bb06eb1 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/Cast.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + struct Cast + { + template static constexpr intptr_t getCastOffset() + { + auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); + auto service = static_cast(implementation); + return reinterpret_cast(service) - reinterpret_cast(implementation); + }; + + static void *applyCastOffset(void *ptr, const intptr_t offset) + { + const auto casted = reinterpret_cast(ptr) + offset; + return reinterpret_cast(casted); + }; + }; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/CastOffset.hpp b/Include/SevenBit/DI/Details/Utils/CastOffset.hpp deleted file mode 100644 index 2dc16d3..0000000 --- a/Include/SevenBit/DI/Details/Utils/CastOffset.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -namespace sb::di::details::utils -{ - template struct CastOffset - { - static constexpr int get() - { - auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); - TService *service = implementation; - return reinterpret_cast(service) - reinterpret_cast(implementation); - }; - }; -} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 28b1d47..3263711 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -3,8 +3,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" - namespace sb::di::details::utils { struct EXPORT Check @@ -19,13 +17,5 @@ namespace sb::di::details::utils { return std::is_enum_v && value >= 0 && value < TEnum::Count; } - - static bool instanceValidity(const ServiceInstance::Ptr &instance); - - static bool instanceValidity(const ServiceInstance *instance); }; } // namespace sb::di::details::utils - -#ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Details/Utils/Impl/Check.hpp" -#endif diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp deleted file mode 100644 index 58dec46..0000000 --- a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Utils/Check.hpp" - -namespace sb::di::details::utils -{ - INLINE bool Check::instanceValidity(const ServiceInstance::Ptr &instance) - { - return instanceValidity(instance.get()); - } - - INLINE bool Check::instanceValidity(const ServiceInstance *instance) - { - return notNull(instance) && instance->isValid(); - } -} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp deleted file mode 100644 index 8f9732a..0000000 --- a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/Exceptions.hpp" - -namespace sb::di::details::utils -{ - INLINE ServiceInstance::Ptr Require::validInstanceAndGet(ServiceInstance::Ptr &&instance) - { - validInstance(instance.get()); - return std::move(instance); - } - - INLINE ServiceInstance &Require::validInstanceAndGet(ServiceInstance *instance) - { - validInstance(instance); - return *instance; - } - - INLINE void Require::validInstance(const ServiceInstance::Ptr &instance) { validInstance(instance.get()); } - - INLINE void Require::validInstance(const ServiceInstance *instance) - { - notNull(instance); - if (!Check::instanceValidity(instance)) - { - throw InvalidServiceException{instance->getTypeId()}; - } - } -} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index f1895fe..6d07c74 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -6,7 +6,6 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { @@ -67,17 +66,5 @@ namespace sb::di::details::utils std::to_string(TEnum::Count) + ")"}; } } - - static ServiceInstance::Ptr validInstanceAndGet(ServiceInstance::Ptr &&instance); - - static ServiceInstance &validInstanceAndGet(ServiceInstance *instance); - - static void validInstance(const ServiceInstance::Ptr &instance); - - static void validInstance(const ServiceInstance *instance); }; } // namespace sb::di::details::utils - -#ifdef _7BIT_DI_ADD_IMPL -#include "SevenBit/DI/Details/Utils/Impl/Require.hpp" -#endif diff --git a/Include/SevenBit/DI/IServiceFactory.hpp b/Include/SevenBit/DI/IServiceFactory.hpp index af65ecf..9d12263 100644 --- a/Include/SevenBit/DI/IServiceFactory.hpp +++ b/Include/SevenBit/DI/IServiceFactory.hpp @@ -4,7 +4,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di { @@ -15,15 +15,10 @@ namespace sb::di using Ptr = std::unique_ptr; using SPtr = std::shared_ptr; - /** - * @brief Get the TypeId of the service instances that the factory will create - */ - [[nodiscard]] virtual TypeId getServiceTypeId() const = 0; - /** * @brief Create a service instance object */ - virtual ServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, bool inPlaceRequest) const = 0; + virtual IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, bool inPlaceRequest) const = 0; virtual ~IServiceFactory() = default; }; diff --git a/Include/SevenBit/DI/IServiceInstance.hpp b/Include/SevenBit/DI/IServiceInstance.hpp new file mode 100644 index 0000000..a3d8019 --- /dev/null +++ b/Include/SevenBit/DI/IServiceInstance.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/TypeId.hpp" + +namespace sb::di +{ + struct IServiceInstance + { + using Ptr = std::unique_ptr; + using SPtr = std::shared_ptr; + + /** + * @brief Returns service pointer as void * + */ + [[nodiscard]] virtual void *get() const = 0; + + /** + * @brief Returns service pointer as void *, + * @details Method is used to ensure that service can be moved out + * @throws sb::di::CannotMoveOutServiceException + * + * Example: + * @code{.cpp} + * void* service = instance->getForMoveOut(); + * @endcode + */ + [[nodiscard]] virtual void *getForMoveOut() = 0; + + /** + * @brief Releases service ownership as void * + * @details If instance is owner of service it will release this ownership just like + * std::unique_ptr::release(), otherwise it will throw exception + * @throws sb::di::CannotReleaseServiceException + * @warning Using this method might cause memory leaks, client is responsible for managing this pointner + * lifetime, the best approach is to immediately wrap this pointer with proper std::unique_ptr + * + * Example: + * @code{.cpp} + * std::unique_ptr service{static_cast(instance->release())}; + * @endcode + */ + [[nodiscard]] virtual void *release() = 0; + + /** + * @brief Get the TypeId of service + * @details This method can be used to check if casting is safe + * + * Example: + * @code{.cpp} + * if(instance->getTypeId() == typeid(T)) { + * T* service = instance->getAs(); + * } + * @endcode + */ + [[nodiscard]] virtual TypeId getTypeId() const = 0; + + /** + * @brief Checks if service instance is valid + * @details If service instance is invalid, get and move methods might lead to undefined behaviour + */ + [[nodiscard]] virtual bool isValid() const = 0; + + virtual ~IServiceInstance() = default; + }; +} // namespace sb::di diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index 3f08f18..c889bfc 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -5,8 +5,8 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/OneOrList.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" #include "SevenBit/DI/TypeId.hpp" @@ -51,39 +51,39 @@ namespace sb::di * @brief Returns service instances * @details If service instance was not registered or was registered as transient, method returns null */ - virtual const OneOrList *tryGetInstances(TypeId serviceTypeId) = 0; + virtual const OneOrList *tryGetInstances(TypeId serviceTypeId) = 0; /** * @brief Creates service instance unique pointer, might throw exception * @details If service was not registered or was registered as scoped/singleton, method throw exception * @throws sb::di::ServiceNotFoundException */ - virtual ServiceInstance::Ptr createInstance(TypeId serviceTypeId) = 0; + virtual ServiceInstance createInstance(TypeId serviceTypeId) = 0; /** * @brief Creates service instance unique pointer, might be null * @details If service was not registered or was registered as scoped/singleton, method returns null */ - virtual ServiceInstance::Ptr tryCreateInstance(TypeId serviceTypeId) = 0; + virtual ServiceInstance tryCreateInstance(TypeId serviceTypeId) = 0; /** * @brief Creates service instances * @details If service was not registered or was registered as scoped/singleton, method returns null option */ - virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; + virtual std::optional> tryCreateInstances(TypeId serviceTypeId) = 0; /** * @brief Creates service instance in place, might throw exception * @details If service was not registered or was registered as scoped/singleton, method throws exception * @throws sb::di::ServiceNotFoundException */ - virtual ServiceInstance::Ptr createInstanceInPlace(TypeId serviceTypeId) = 0; + virtual ServiceInstance createInstanceInPlace(TypeId serviceTypeId) = 0; /** * @brief Creates service instance in place * @details If service was not registered or was registered as scoped/singleton, method returns null */ - virtual ServiceInstance::Ptr tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; + virtual ServiceInstance tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; virtual ~IServiceInstanceProvider() = default; }; diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index f2f302e..d1315ce 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -7,39 +7,35 @@ namespace sb::di { - INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const ServiceLifeTime lifeTime, - IServiceFactory::Ptr implementationFactory, const int castOffset, - const bool isAlias) - : _serviceTypeId(serviceTypeId), _lifeTime(lifeTime), _isAlias(isAlias), + INLINE ServiceDescriptor::ServiceDescriptor(const TypeId serviceTypeId, const TypeId implementationTypeId, + const ServiceLifeTime lifeTime, + IServiceFactory::Ptr implementationFactory, const ptrdiff_t castOffset) + : _serviceTypeId(serviceTypeId), _implementationTypeId(implementationTypeId), _lifeTime(lifeTime), _implementationFactory(std::move(implementationFactory)), _castOffset(castOffset) { - details::utils::Require::notNull(_implementationFactory, "Implementation factory cannot be null"); } - INLINE ServiceLifeTime ServiceDescriptor::getLifeTime() const { return _lifeTime; } - INLINE TypeId ServiceDescriptor::getServiceTypeId() const { return _serviceTypeId; } - INLINE TypeId ServiceDescriptor::getImplementationTypeId() const - { - return getImplementationFactory().getServiceTypeId(); - } + INLINE TypeId ServiceDescriptor::getImplementationTypeId() const { return _implementationTypeId; } + + INLINE ServiceLifeTime ServiceDescriptor::getLifeTime() const { return _lifeTime; } INLINE const IServiceFactory &ServiceDescriptor::getImplementationFactory() const { - return *_implementationFactory; + return *details::utils::Require::notNullAndGet(_implementationFactory.get()); } - INLINE int ServiceDescriptor::getCastOffset() const { return _castOffset; } + INLINE ptrdiff_t ServiceDescriptor::getCastOffset() const { return _castOffset; } - INLINE bool ServiceDescriptor::isAlias() const { return _isAlias; } + INLINE bool ServiceDescriptor::isAlias() const { return !_implementationFactory; } INLINE bool ServiceDescriptor::operator==(const ServiceDescriptor &descriptor) const { - return _isAlias == descriptor.isAlias() && _serviceTypeId == descriptor.getServiceTypeId() && - _lifeTime == descriptor.getLifeTime() && - _implementationFactory.get() == &descriptor.getImplementationFactory(); + return _serviceTypeId == descriptor._serviceTypeId && + _implementationTypeId == descriptor._implementationTypeId && _lifeTime == descriptor._lifeTime && + _implementationFactory == descriptor._implementationFactory && _castOffset == descriptor._castOffset; } INLINE bool ServiceDescriptor::operator!=(const ServiceDescriptor &descriptor) const diff --git a/Include/SevenBit/DI/Impl/ServiceInstance.hpp b/Include/SevenBit/DI/Impl/ServiceInstance.hpp new file mode 100644 index 0000000..0b42ea1 --- /dev/null +++ b/Include/SevenBit/DI/Impl/ServiceInstance.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Utils/Cast.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" + +namespace sb::di +{ + INLINE ServiceInstance::ServiceInstance(IServiceInstance::Ptr implementation, const ptrdiff_t castOffset) + : _implementation(std::move(implementation)), _castOffset(castOffset) + { + details::utils::Require::notNull(_implementation); + if (!_implementation->isValid()) + { + throw InvalidServiceException{_implementation->getTypeId()}; + } + } + + INLINE IServiceInstance &ServiceInstance::getImplementation() + { + return *details::utils::Require::notNullAndGet(_implementation.get()); + } + + INLINE const IServiceInstance &ServiceInstance::getImplementation() const + { + return *details::utils::Require::notNullAndGet(_implementation.get()); + } + + INLINE void ServiceInstance::addCastOffset(const ptrdiff_t castOffset) { _castOffset += castOffset; } + + INLINE bool ServiceInstance::isValid() const { return _implementation && _implementation->isValid(); } + + INLINE ServiceInstance::operator bool() const { return isValid(); } + + INLINE void ServiceInstance::clear() + { + if (_implementation) + { + _implementation.reset(); + } + _castOffset = 0; + } + + INLINE void *ServiceInstance::applyOffset(void *ptr) const + { + return details::utils::Cast::applyCastOffset(ptr, _castOffset); + } + +} // namespace sb::di diff --git a/Include/SevenBit/DI/OneOrList.hpp b/Include/SevenBit/DI/OneOrList.hpp index 671cb63..1255f43 100644 --- a/Include/SevenBit/DI/OneOrList.hpp +++ b/Include/SevenBit/DI/OneOrList.hpp @@ -99,6 +99,50 @@ namespace sb::di } } + template void forEach(TFunc fcn) + { + if (auto instance = tryGetAsSingle()) + { + callFcn(fcn, *instance, 0); + return; + } + size_t index = 0; + for (auto &instance : getAsList()) + { + callFcn(fcn, instance, index++); + } + } + + template void forEach(TFunc fcn) const + { + if (const auto instance = tryGetAsSingle()) + { + callFcn(fcn, *instance, 0); + return; + } + size_t index = 0; + for (const auto &instance : getAsList()) + { + callFcn(fcn, instance, index++); + } + } + + template auto map(TFunc mapFcn) + { + std::vector result; + result.reserve(size()); + forEach([&](T &item, size_t index) { result.push_back(callFcn(mapFcn, item, index)); }); + return result; + } + + template auto map(TFunc mapFcn) const + { + std::vector result; + result.reserve(size()); + forEach([&](const T &item, size_t index) { result.push_back(callFcn(mapFcn, item, index)); }); + return result; + } + private: void tryConvertToList() { @@ -109,6 +153,28 @@ namespace sb::di _variant = std::move(vec); } } + + template static auto callFcn(TFunc &fcn, TItem &item, size_t index) + { + if constexpr (std::is_invocable_v) + { + return fcn(item); + } + else if constexpr (std::is_invocable_v) + { + return fcn(item, index); + } + else + { + badFunctor(); + } + } + + template static void badFunctor() + { + static_assert(details::utils::notSupportedType, + "Functor should contain as arguments: T, additionally index"); + } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index f14d788..bf6e65e 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -9,7 +9,7 @@ #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" #include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" -#include "SevenBit/DI/Details/Utils/CastOffset.hpp" +#include "SevenBit/DI/Details/Utils/Cast.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" @@ -108,8 +108,8 @@ namespace sb::di details::utils::Assert::inheritance(); auto factory = std::make_unique>(); - return {typeid(TService), lifetime, std::move(factory), - details::utils::CastOffset::get()}; + return {typeid(TService), typeid(TImplementation), lifetime, std::move(factory), + details::utils::Cast::getCastOffset()}; } /** @@ -163,8 +163,8 @@ namespace sb::di details::utils::Assert::inheritance(); auto factory = std::make_unique>(service); - return {typeid(TService), ServiceLifeTimes::Singleton, std::move(factory), - details::utils::CastOffset::get()}; + return {typeid(TService), typeid(TImplementation), ServiceLifeTimes::Singleton, std::move(factory), + details::utils::Cast::getCastOffset()}; } /** @@ -351,8 +351,8 @@ namespace sb::di details::utils::Assert::factoryInheritance(); auto factory = std::make_unique(std::forward(factoryFcn)); - return {typeid(TRealService), lifetime, std::move(factory), - details::utils::CastOffset::get()}; + return {typeid(TRealService), typeid(TImplementation), lifetime, std::move(factory), + details::utils::Cast::getCastOffset()}; } template static ServiceDescriptor describeAlias() @@ -360,9 +360,8 @@ namespace sb::di details::utils::Assert::aliasNotSame(); details::utils::Assert::aliasInheritance(); - auto factory = std::make_unique>(); - return {typeid(TAlias), ServiceLifeTimes::Scoped, std::move(factory), - details::utils::CastOffset::get(), true}; + return {typeid(TAlias), typeid(TService), ServiceLifeTimes::Scoped, nullptr, + details::utils::Cast::getCastOffset()}; } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index cc1a6d2..e666170 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -13,10 +13,10 @@ namespace sb::di class EXPORT ServiceDescriptor { TypeId _serviceTypeId; + TypeId _implementationTypeId; ServiceLifeTime _lifeTime; - bool _isAlias; IServiceFactory::SPtr _implementationFactory; - int _castOffset; + ptrdiff_t _castOffset; public: using Ptr = std::unique_ptr; @@ -26,20 +26,15 @@ namespace sb::di * @details implementationFactory cannot be null, otherwise constructor will throw exception * @throws sb::di::NullPointerException */ - ServiceDescriptor(TypeId serviceTypeId, ServiceLifeTime lifeTime, IServiceFactory::Ptr implementationFactory, - int castOffset = 0, bool isAlias = false); + ServiceDescriptor(TypeId serviceTypeId, TypeId implementationTypeId, ServiceLifeTime lifeTime, + IServiceFactory::Ptr implementationFactory, ptrdiff_t castOffset = 0); ServiceDescriptor(const ServiceDescriptor &other) = default; - ServiceDescriptor(ServiceDescriptor &&) = default; + ServiceDescriptor(ServiceDescriptor &&other) = default; ServiceDescriptor &operator=(const ServiceDescriptor &other) = default; ServiceDescriptor &operator=(ServiceDescriptor &&other) = default; - /** - * @brief Get the lifetime object - */ - [[nodiscard]] ServiceLifeTime getLifeTime() const; - /** * @brief Get the service TypeId */ @@ -50,12 +45,17 @@ namespace sb::di */ [[nodiscard]] TypeId getImplementationTypeId() const; + /** + * @brief Get the lifetime object + */ + [[nodiscard]] ServiceLifeTime getLifeTime() const; + /** * @brief Get the service implementation factory */ [[nodiscard]] const IServiceFactory &getImplementationFactory() const; - [[nodiscard]] int getCastOffset() const; + [[nodiscard]] ptrdiff_t getCastOffset() const; /** * @brief Check if service is alias diff --git a/Include/SevenBit/DI/ServiceInstance.hpp b/Include/SevenBit/DI/ServiceInstance.hpp index 571050d..f84b575 100644 --- a/Include/SevenBit/DI/ServiceInstance.hpp +++ b/Include/SevenBit/DI/ServiceInstance.hpp @@ -4,75 +4,44 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/TypeId.hpp" +#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di { class ServiceInstance { - int _getOffset = 0; + IServiceInstance::Ptr _implementation; + ptrdiff_t _castOffset = 0; public: - /** - * @brief Returns service pointer as void * - */ - [[nodiscard]] virtual void *get() const = 0; + using Ptr = std::unique_ptr; - /** - * @brief Returns service pointer as void *, - * @details Method is used to ensure that service can be moved out - * @throws sb::di::CannotMoveOutServiceException - * - * Example: - * @code{.cpp} - * void* service = instance->getForMoveOut(); - * @endcode - */ - [[nodiscard]] virtual void *getForMoveOut() = 0; + ServiceInstance() = default; - /** - * @brief Releases service ownership as void * - * @details If instance is owner of service it will release this ownership just like - * std::unique_ptr::release(), otherwise it will throw exception - * @throws sb::di::CannotReleaseServiceException - * @warning Using this method might cause memory leaks, client is responsible for managing this pointner - * lifetime, the best approach is to immediately wrap this pointer with proper std::unique_ptr - * - * Example: - * @code{.cpp} - * std::unique_ptr service{static_cast(instance->release())}; - * @endcode - */ - [[nodiscard]] virtual void *release() = 0; + explicit ServiceInstance(IServiceInstance::Ptr implementation, ptrdiff_t castOffset = 0); - public: - using Ptr = std::unique_ptr; + ServiceInstance(const ServiceInstance &other) = delete; + ServiceInstance(ServiceInstance &&other) = default; - void addGetOffset(const int offset) { _getOffset += offset; } + ServiceInstance &operator=(const ServiceInstance &other) = delete; + ServiceInstance &operator=(ServiceInstance &&other) = default; - /** - * @brief Get the TypeId of service - * @details This method can be used to check if casting is safe - * - * Example: - * @code{.cpp} - * if(instance->getTypeId() == typeid(T)) { - * T* service = instance->getAs(); - * } - * @endcode - */ - [[nodiscard]] virtual TypeId getTypeId() const = 0; + IServiceInstance &getImplementation(); + + [[nodiscard]] const IServiceInstance &getImplementation() const; + + void addCastOffset(ptrdiff_t castOffset); /** * @brief Checks if service instance is valid * @details If service instance is invalid, get and move methods might lead to undefined behaviour */ - [[nodiscard]] virtual bool isValid() const = 0; + [[nodiscard]] bool isValid() const; /** * @brief Wrapper around isValid method */ - explicit operator bool() const { return isValid(); } + explicit operator bool() const; /** * @brief Returns service pointer as T * @@ -83,7 +52,10 @@ namespace sb::di * T* service = instance->getAs(); * @endcode */ - template [[nodiscard]] T *getAs() const { return static_cast(applyOffset(get())); } + template [[nodiscard]] T *getAs() const + { + return static_cast(applyOffset(getImplementation().get())); + } /** * @brief Releases service ownership as pointer T * @@ -94,7 +66,7 @@ namespace sb::di * T* service = instance->releaseAs(); * @endcode */ - template T *releaseAs() { return static_cast(applyOffset(release())); } + template T *releaseAs() { return static_cast(applyOffset(getImplementation().release())); } /** * @brief Moves out service as unique_ptr @@ -116,11 +88,18 @@ namespace sb::di * T service = instance->moveOutAs(); * @endcode */ - template T &&moveOutAs() { return std::move(*static_cast(applyOffset(getForMoveOut()))); } + template T &&moveOutAs() + { + return std::move(*static_cast(applyOffset(getImplementation().getForMoveOut()))); + } - virtual ~ServiceInstance() = default; + void clear(); private: - void *applyOffset(void *ptr) const { return static_cast(ptr) + _getOffset; } + void *applyOffset(void *ptr) const; }; } // namespace sb::di + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Impl/ServiceInstance.hpp" +#endif diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index 5092134..e64b301 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -106,7 +106,7 @@ namespace sb::di template TService *tryGetService() { if (const auto instance = getInstanceProvider().tryGetInstance(typeid(TService)); - details::utils::Check::instanceValidity(instance)) + checkInstanceValidity(instance)) { return instance->getAs(); } @@ -128,7 +128,7 @@ namespace sb::di template TService &getService() { auto &instance = getInstanceProvider().getInstance(typeid(TService)); - details::utils::Require::validInstance(&instance); + requireValidInstance(instance); return *instance.getAs(); } @@ -150,8 +150,10 @@ namespace sb::di { if (auto instances = getInstanceProvider().tryGetInstances(typeid(TService))) { - return mapValidInstances( - *instances, [](const ServiceInstance::Ptr &instance) { return instance->getAs(); }); + return instances->map([&](const ServiceInstance &instance) { + requireValidInstance(instance); + return instance.getAs(); + }); } return {}; } @@ -169,10 +171,10 @@ namespace sb::di */ template std::unique_ptr tryCreateService() { - if (const auto instance = getInstanceProvider().tryCreateInstance(typeid(TService)); - details::utils::Check::instanceValidity(instance)) + if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService)); + checkInstanceValidity(&instance)) { - return instance->moveOutAsUniquePtr(); + return instance.moveOutAsUniquePtr(); } return nullptr; } @@ -191,9 +193,9 @@ namespace sb::di */ template std::unique_ptr createService() { - const auto instance = getInstanceProvider().createInstance(typeid(TService)); - details::utils::Require::validInstance(instance); - return instance->moveOutAsUniquePtr(); + auto instance = getInstanceProvider().createInstance(typeid(TService)); + requireValidInstance(instance); + return instance.moveOutAsUniquePtr(); } /** @@ -211,8 +213,8 @@ namespace sb::di template TService createServiceInPlace() { const auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); - details::utils::Require::validInstance(instance); - return instance->moveOutAs(); + requireValidInstance(instance); + return instance.moveOutAs(); } /** @@ -233,35 +235,23 @@ namespace sb::di { if (auto instances = getInstanceProvider().tryCreateInstances(typeid(TService))) { - return mapValidInstances(*instances, [](const ServiceInstance::Ptr &instance) { - return instance->moveOutAsUniquePtr(); + return instances->map([&](ServiceInstance &instance) { + requireValidInstance(instance); + return instance.moveOutAsUniquePtr(); }); } return {}; } private: - template auto mapValidInstances(OneOrList &instances, TFunc mapFunction) + static bool checkInstanceValidity(const ServiceInstance *instance) { return instance && instance->isValid(); } + + static void requireValidInstance(const ServiceInstance &instance) { - std::vector result; - if (auto instance = instances.tryGetAsSingle()) - { - if (details::utils::Check::instanceValidity(*instance)) - { - result.reserve(1); - result.emplace_back(mapFunction(*instance)); - } - return result; - } - result.reserve(instances.size()); - for (auto &instance : instances.getAsList()) + if (!instance.isValid()) { - if (details::utils::Check::instanceValidity(instance)) - { - result.emplace_back(mapFunction(instance)); - } + throw InvalidServiceException(instance.getImplementation().getTypeId()); } - return result; } }; } // namespace sb::di diff --git a/Source/Source.cpp b/Source/Source.cpp index 7bc4f2c..e448b0f 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -11,8 +11,7 @@ #include "SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp" #include "SevenBit/DI/Details/Helpers/Impl/CircularDependencyGuard.hpp" #include "SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp" -#include "SevenBit/DI/Details/Utils/Impl/Check.hpp" -#include "SevenBit/DI/Details/Utils/Impl/Require.hpp" #include "SevenBit/DI/Impl/Exceptions.hpp" #include "SevenBit/DI/Impl/ServiceCollection.hpp" #include "SevenBit/DI/Impl/ServiceDescriptor.hpp" +#include "SevenBit/DI/Impl/ServiceInstance.hpp" From 810672d53abcab624e6a75e2fe64ab226ffa309d Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Fri, 2 Feb 2024 21:31:39 +0100 Subject: [PATCH 31/45] refactor code --- .../Containers/Impl/ServiceInstanceList.hpp | 12 +------ .../Containers/ServiceInstanceList.hpp | 1 - .../Core/Impl/ServiceInstanceProvider.hpp | 22 ++++-------- .../Core/Impl/ServiceInstancesResolver.hpp | 36 ++++++++++++++----- .../Details/Core/ServiceInstanceProvider.hpp | 4 +-- Include/SevenBit/DI/OneOrList.hpp | 8 +++-- 6 files changed, 42 insertions(+), 41 deletions(-) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp index a1778ec..04b5ae6 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp @@ -12,17 +12,7 @@ namespace sb::di::details::containers INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance instance) : _oneOrList(std::move(instance)) {} - INLINE void ServiceInstanceList::add(ServiceInstance &&service) - { - if (const auto single = _oneOrList.tryGetAsSingle(); single && !single->isValid()) - { - *single = std::move(service); - } - else - { - _oneOrList.add(std::move(service)); - } - } + INLINE void ServiceInstanceList::add(ServiceInstance &&service) { _oneOrList.add(std::move(service)); } INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index 334e78c..6f29426 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -15,7 +15,6 @@ namespace sb::di::details::containers bool _sealed = false; public: - explicit ServiceInstanceList(); explicit ServiceInstanceList(ServiceInstance instance); explicit ServiceInstanceList(size_t size); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 88798ff..377941a 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -166,11 +166,8 @@ namespace sb::di::details::core { if (descriptors.isAlias()) { - if (const auto original = tryGetInstance(descriptors.last().getImplementationTypeId())) - { - return makeResolver(descriptors).createOneAlias(*original); - } - return std::nullopt; + const auto original = tryGetInstance(descriptors.last().getImplementationTypeId()); + return original ? std::make_optional(makeResolver(descriptors).createOneAlias(*original)) : std::nullopt; } return makeResolver(descriptors).createOneInstanceInPlace(); } @@ -180,11 +177,9 @@ namespace sb::di::details::core { if (descriptors.isAlias()) { - if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) - { - return makeResolver(descriptors).createAllAliases(*originals); - } - return std::nullopt; + const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); + return originals ? std::make_optional(makeResolver(descriptors).createAllAliases(*originals)) + : std::nullopt; } return makeResolver(descriptors).createAllInstancesInPlace(); } @@ -194,11 +189,8 @@ namespace sb::di::details::core { if (descriptors.isAlias()) { - if (const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId())) - { - return &makeResolver(descriptors).createRestAliases(*originals, instances); - } - return nullptr; + const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); + return originals ? &makeResolver(descriptors).createRestAliases(*originals, instances) : nullptr; } return &makeResolver(descriptors).createRestInstancesInPlace(instances); } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index 3206a67..cafb5c2 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -66,8 +66,19 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllAliases( const OneOrList &originals) const { - containers::ServiceInstanceList aliases{createAlias(originals.last())}; - return std::move(createRestAliases(originals, aliases)); + containers::ServiceInstanceList instances{createAlias(originals.first())}; + if (const auto size = originals.size(); size > 1) + { + instances.reserve(size); + originals.forEach([&](const ServiceInstance &instance, const size_t index) { + if (index) // skip first + { + instances.add(createAlias(instance)); + } + }); + } + instances.seal(); + return instances; } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestAliases( @@ -76,14 +87,13 @@ namespace sb::di::details::core if (const auto size = originals.size(); size > 1) { instances.reserve(size); - auto realFirst = createAlias(originals.first()); originals.forEach([&](const ServiceInstance &instance, const size_t index) { if (index && index < size - 1) // skip first and last { instances.add(createAlias(instance)); } }); - instances.add(std::move(realFirst)); + instances.add(createAlias(originals.first())); std::swap(instances.first(), instances.last()); } instances.seal(); @@ -107,8 +117,19 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList ServiceInstancesResolver::createAllInstances(const bool inPlaceRequest) const { - containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.last(), inPlaceRequest)}; - return std::move(createRestInstances(instances, inPlaceRequest)); + containers::ServiceInstanceList instances{_creator.createInstance(_descriptors.first(), inPlaceRequest)}; + if (const auto size = _descriptors.size(); size > 1) + { + instances.reserve(size); + _descriptors.getInnerList().forEach([&](const ServiceDescriptor &descriptor, const size_t index) { + if (index) // skip first + { + instances.add(_creator.createInstance(descriptor, inPlaceRequest)); + } + }); + } + instances.seal(); + return instances; } INLINE containers::ServiceInstanceList &ServiceInstancesResolver::createRestInstances( @@ -117,14 +138,13 @@ namespace sb::di::details::core if (const auto size = _descriptors.size(); size > 1) { instances.reserve(size); - auto realFirst = _creator.createInstance(_descriptors.first(), inPlaceRequest); _descriptors.getInnerList().forEach([&](const ServiceDescriptor &descriptor, const size_t index) { if (index && index < size - 1) // skip first and last { instances.add(_creator.createInstance(descriptor, inPlaceRequest)); } }); - instances.add(std::move(realFirst)); + instances.add(_creator.createInstance(_descriptors.first(), inPlaceRequest)); std::swap(instances.first(), instances.last()); } instances.seal(); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 3b1f3ba..ceee548 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -24,14 +24,12 @@ namespace sb::di::details::core ServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; - using ServiceDescriptorList = containers::ServiceDescriptorList; - public: using Ptr = std::unique_ptr; ServiceInstanceProvider(ServiceInstanceProviderRoot &root, ServiceProviderOptions options); - ServiceInstanceProvider(ServiceInstanceProvider &&) noexcept = delete; + ServiceInstanceProvider(ServiceInstanceProvider &&) = delete; ServiceInstanceProvider(const ServiceInstanceProvider &) = delete; ServiceInstanceProvider &operator=(const ServiceInstanceProvider &) = delete; diff --git a/Include/SevenBit/DI/OneOrList.hpp b/Include/SevenBit/DI/OneOrList.hpp index 1255f43..949ab1c 100644 --- a/Include/SevenBit/DI/OneOrList.hpp +++ b/Include/SevenBit/DI/OneOrList.hpp @@ -5,6 +5,8 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/NotSupportedType.hpp" + namespace sb::di { template class OneOrList @@ -156,11 +158,11 @@ namespace sb::di template static auto callFcn(TFunc &fcn, TItem &item, size_t index) { - if constexpr (std::is_invocable_v) + if constexpr (std::is_invocable_v) { return fcn(item); } - else if constexpr (std::is_invocable_v) + else if constexpr (std::is_invocable_v) { return fcn(item, index); } @@ -173,7 +175,7 @@ namespace sb::di template static void badFunctor() { static_assert(details::utils::notSupportedType, - "Functor should contain as arguments: T, additionally index"); + "Functor should take as arguments: T and additionally index"); } }; From c1d85a8527af875917267d62a2a528b9e277b10b Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 3 Feb 2024 17:11:05 +0100 Subject: [PATCH 32/45] fix tests --- .../Core/Impl/ServiceInstancesResolver.hpp | 6 +- .../Details/Factories/VoidServiceFactory.hpp | 23 -- Include/SevenBit/DI/Exceptions.hpp | 1 + Include/SevenBit/DI/Impl/Exceptions.hpp | 5 + Include/SevenBit/DI/ServiceCollection.hpp | 10 +- Include/SevenBit/DI/ServiceDescriber.hpp | 1 - Include/SevenBit/DI/ServiceProvider.hpp | 4 +- Tests/Helpers/Classes/MultiInherit.hpp | 61 +++++ .../Mocks/ServiceInstanceProviderMock.hpp | 14 +- Tests/Integration/MultiInheritanceTest.cpp | 106 +++++++++ .../Containers/ServiceInstanceListTest.cpp | 60 ++--- .../Containers/ServiceInstancesMapTest.cpp | 51 +++-- .../Unit/Core/ServiceInstanceCreatorTest.cpp | 34 +-- .../Core/ServiceInstanceProviderRootTest.cpp | 42 ++-- .../Unit/Core/ServiceInstanceResolverTest.cpp | 216 +++++++++--------- .../Factories/ExternalServiceFactoryTest.cpp | 8 - Tests/Unit/Factories/ServiceFactoryTest.cpp | 71 ++---- .../Unit/Factories/ServiceFcnFactoryTest.cpp | 72 ++---- .../Unit/Factories/VoidServiceFactoryTest.cpp | 44 ---- Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp | 2 +- .../Helpers/ServiceFactoryInvokerTest.cpp | 2 +- .../Unit/Helpers/ServiceParamProviderTest.cpp | 40 ++-- Tests/Unit/ServiceDescriptorTest.cpp | 32 +-- Tests/Unit/Services/AliasServiceTest.cpp | 14 +- Tests/Unit/Services/ExternalServiceTest.cpp | 14 +- Tests/Unit/Services/InPlaceServiceTest.cpp | 7 +- Tests/Unit/Services/UniquePtrServiceTest.cpp | 16 +- Tests/Unit/Utils/CheckTest.cpp | 16 -- Tests/Unit/Utils/RequireTest.cpp | 18 -- 29 files changed, 505 insertions(+), 485 deletions(-) delete mode 100644 Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp create mode 100644 Tests/Helpers/Classes/MultiInherit.hpp create mode 100644 Tests/Integration/MultiInheritanceTest.cpp delete mode 100644 Tests/Unit/Factories/VoidServiceFactoryTest.cpp diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index cafb5c2..b163b4f 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -87,13 +87,14 @@ namespace sb::di::details::core if (const auto size = originals.size(); size > 1) { instances.reserve(size); + auto first = createAlias(originals.first()); originals.forEach([&](const ServiceInstance &instance, const size_t index) { if (index && index < size - 1) // skip first and last { instances.add(createAlias(instance)); } }); - instances.add(createAlias(originals.first())); + instances.add(std::move(first)); std::swap(instances.first(), instances.last()); } instances.seal(); @@ -138,13 +139,14 @@ namespace sb::di::details::core if (const auto size = _descriptors.size(); size > 1) { instances.reserve(size); + auto first = _creator.createInstance(_descriptors.first(), inPlaceRequest); _descriptors.getInnerList().forEach([&](const ServiceDescriptor &descriptor, const size_t index) { if (index && index < size - 1) // skip first and last { instances.add(_creator.createInstance(descriptor, inPlaceRequest)); } }); - instances.add(_creator.createInstance(_descriptors.first(), inPlaceRequest)); + instances.add(std::move(first)); std::swap(instances.first(), instances.last()); } instances.seal(); diff --git a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp deleted file mode 100644 index 0eb3c68..0000000 --- a/Include/SevenBit/DI/Details/Factories/VoidServiceFactory.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -#include "SevenBit/DI/LibraryConfig.hpp" - -#include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/TypeId.hpp" - -namespace sb::di::details::factories -{ - - template class VoidServiceFactory final : public IServiceFactory - { - public: - IServiceInstance::Ptr createInstance(ServiceProvider &serviceProvider, const bool inPlaceRequest) const override - { - return nullptr; - } - }; - -} // namespace sb::di::details::factories diff --git a/Include/SevenBit/DI/Exceptions.hpp b/Include/SevenBit/DI/Exceptions.hpp index 455ae46..c1a7224 100644 --- a/Include/SevenBit/DI/Exceptions.hpp +++ b/Include/SevenBit/DI/Exceptions.hpp @@ -24,6 +24,7 @@ namespace sb::di struct EXPORT InvalidServiceException : InjectorException { + explicit InvalidServiceException(); explicit InvalidServiceException(TypeId typeId); }; diff --git a/Include/SevenBit/DI/Impl/Exceptions.hpp b/Include/SevenBit/DI/Impl/Exceptions.hpp index 5a2894d..8f40e45 100644 --- a/Include/SevenBit/DI/Impl/Exceptions.hpp +++ b/Include/SevenBit/DI/Impl/Exceptions.hpp @@ -12,6 +12,11 @@ namespace sb::di INLINE NullPointerException::NullPointerException(const std::string &why) : InjectorException{why} {} + INLINE InvalidServiceException::InvalidServiceException() + : InjectorException{std::string{"Service is in not valid state."}} + { + } + INLINE InvalidServiceException::InvalidServiceException(const TypeId typeId) : InjectorException{std::string{"Service: '"} + typeId.name() + "' is in not valid state."} { diff --git a/Include/SevenBit/DI/ServiceCollection.hpp b/Include/SevenBit/DI/ServiceCollection.hpp index a625e33..b8eb975 100644 --- a/Include/SevenBit/DI/ServiceCollection.hpp +++ b/Include/SevenBit/DI/ServiceCollection.hpp @@ -450,11 +450,6 @@ namespace sb::di return add(ServiceDescriber::describeSingleton(service)); } - template ServiceCollection &addAlias() - { - return add(ServiceDescriber::describeAlias()); - } - /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -622,6 +617,11 @@ namespace sb::di { return add(ServiceDescriber::describeTransientFrom(std::move(factory))); } + + template ServiceCollection &addAlias() + { + return add(ServiceDescriber::describeAlias()); + } }; } // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index bf6e65e..8851143 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" -#include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" #include "SevenBit/DI/Details/Utils/Assert.hpp" #include "SevenBit/DI/Details/Utils/Cast.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index e64b301..859c0eb 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -212,7 +212,7 @@ namespace sb::di */ template TService createServiceInPlace() { - const auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); + auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); requireValidInstance(instance); return instance.moveOutAs(); } @@ -250,7 +250,7 @@ namespace sb::di { if (!instance.isValid()) { - throw InvalidServiceException(instance.getImplementation().getTypeId()); + throw InvalidServiceException(); } } }; diff --git a/Tests/Helpers/Classes/MultiInherit.hpp b/Tests/Helpers/Classes/MultiInherit.hpp new file mode 100644 index 0000000..e92f616 --- /dev/null +++ b/Tests/Helpers/Classes/MultiInherit.hpp @@ -0,0 +1,61 @@ +#pragma once + +struct TestMultiInheritClass1 +{ + int arr[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 1; + virtual int first() { return 1; } + + virtual ~TestMultiInheritClass1() = default; +}; +struct TestMultiInherit2Class1 +{ + int arr[30] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 2; + virtual int second() { return 11; } + + virtual ~TestMultiInherit2Class1() = default; +}; +struct TestMultiInheritClass2 : TestMultiInheritClass1, TestMultiInherit2Class1 +{ + int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 3; + int first() override { return 2; } + int second() override { return 22; } +}; +struct TestMultiInherit3Class1 +{ + int arr[40] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 4; + virtual int third() { return 111; } + + virtual ~TestMultiInherit3Class1() = default; +}; + +struct TestMultiInheritClass3 : TestMultiInheritClass2, TestMultiInherit3Class1 +{ + int arr[50] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 5; + int first() override { return 3; } + int second() override { return 33; } + int third() override { return 333; } +}; + +struct TestMultiInherit4Class4 +{ + int arr[80] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 6; + virtual int fourth() { return 1111; } + + virtual ~TestMultiInherit4Class4() = default; +}; + +struct TestMultiInheritClass4 : TestMultiInheritClass3, TestMultiInherit4Class4 +{ + int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int end = 7; + int first() override { return 4; } + int second() override { return 44; } + int third() override { return 444; } + int fourth() override { return 4444; } +}; diff --git a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp index 2305988..b4b0d3a 100644 --- a/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp +++ b/Tests/Helpers/Mocks/ServiceInstanceProviderMock.hpp @@ -11,12 +11,12 @@ struct ServiceInstanceProviderMock : public sb::di::IServiceInstanceProvider MOCK_METHOD((void), init, (sb::di::ServiceProvider &), (override)); MOCK_METHOD((const sb::di::ServiceInstance *), tryGetInstance, (sb::di::TypeId serviceTypeId), (override)); MOCK_METHOD((const sb::di::ServiceInstance &), getInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((const sb::di::OneOrList *), tryGetInstances, - (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::ServiceInstance::Ptr), tryCreateInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::ServiceInstance::Ptr), createInstance, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::ServiceInstance::Ptr), tryCreateInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((sb::di::ServiceInstance::Ptr), createInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); - MOCK_METHOD((std::optional>), tryCreateInstances, + MOCK_METHOD((const sb::di::OneOrList *), tryGetInstances, (sb::di::TypeId serviceTypeId), + (override)); + MOCK_METHOD((sb::di::ServiceInstance), tryCreateInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance), createInstance, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance), tryCreateInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((sb::di::ServiceInstance), createInstanceInPlace, (sb::di::TypeId serviceTypeId), (override)); + MOCK_METHOD((std::optional>), tryCreateInstances, (sb::di::TypeId serviceTypeId), (override)); }; diff --git a/Tests/Integration/MultiInheritanceTest.cpp b/Tests/Integration/MultiInheritanceTest.cpp new file mode 100644 index 0000000..3083829 --- /dev/null +++ b/Tests/Integration/MultiInheritanceTest.cpp @@ -0,0 +1,106 @@ +#include +#include + +#include "../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class MultiInheritanceTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + MultiInheritanceTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~MultiInheritanceTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(MultiInheritanceTest, ShouldGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + auto service3 = provider.createService(); + auto service4 = provider.createService(); + auto &service5 = provider.getService(); + auto &service6 = provider.getService(); + + EXPECT_EQ(service1.first(), 2); + EXPECT_EQ(service1.arr[0], 1); + EXPECT_EQ(service1.arr[8], 9); + EXPECT_EQ(service1.end, 1); + EXPECT_EQ(service2.second(), 22); + EXPECT_EQ(service2.arr[0], 1); + EXPECT_EQ(service2.arr[8], 9); + EXPECT_EQ(service2.end, 2); + EXPECT_EQ(service3->first(), 3); + EXPECT_EQ(service3->second(), 33); + EXPECT_EQ(service3->arr[0], 1); + EXPECT_EQ(service3->arr[8], 9); + EXPECT_EQ(service3->end, 3); + EXPECT_EQ(service4->third(), 333); + EXPECT_EQ(service4->arr[0], 1); + EXPECT_EQ(service4->arr[8], 9); + EXPECT_EQ(service4->end, 4); + EXPECT_EQ(service5.first(), 4); + EXPECT_EQ(service5.second(), 44); + EXPECT_EQ(service5.third(), 444); + EXPECT_EQ(service5.arr[0], 1); + EXPECT_EQ(service5.arr[8], 9); + EXPECT_EQ(service5.end, 5); + EXPECT_EQ(service6.fourth(), 4444); + EXPECT_EQ(service6.arr[0], 1); + EXPECT_EQ(service6.arr[8], 9); + EXPECT_EQ(service6.end, 6); +} + +TEST_F(MultiInheritanceTest, ShouldGetAliasesService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + auto service3 = provider.createService(); + auto service4 = provider.createService(); + + EXPECT_EQ(service1.first(), 2); + EXPECT_EQ(service1.arr[0], 1); + EXPECT_EQ(service1.arr[8], 9); + EXPECT_EQ(service1.end, 1); + EXPECT_EQ(service2.second(), 22); + EXPECT_EQ(service2.arr[0], 1); + EXPECT_EQ(service2.arr[8], 9); + EXPECT_EQ(service2.end, 2); + EXPECT_EQ(service3->first(), 4); + EXPECT_EQ(service3->second(), 44); + EXPECT_EQ(service3->third(), 444); + EXPECT_EQ(service3->arr[0], 1); + EXPECT_EQ(service3->arr[8], 9); + EXPECT_EQ(service3->end, 5); + EXPECT_EQ(service4->fourth(), 4444); + EXPECT_EQ(service4->arr[0], 1); + EXPECT_EQ(service4->arr[8], 9); + EXPECT_EQ(service4->end, 6); +} diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index c8bbc41..0dc7f37 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -20,7 +20,7 @@ class ServiceInstanceListTest : public testing::Test void TearDown() override {} - ~ServiceInstanceListTest() override {} + ~ServiceInstanceListTest() override = default; static void TearDownTestSuite() {} }; @@ -28,25 +28,25 @@ class ServiceInstanceListTest : public testing::Test TEST_F(ServiceInstanceListTest, ShouldAddServices) { TestClass1 test; - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::ExternalService{&test}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::ExternalService{&test}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + list.add(sb::di::ServiceInstance{std::move(instance2)}); } -TEST_F(ServiceInstanceListTest, ShouldFailAddNullService) +TEST_F(ServiceInstanceListTest, ShouldNotFailAddNullService) { - auto act = [&]() { sb::di::details::containers::ServiceInstanceList list{nullptr}; }; + auto act = [&]() { sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{}}; }; - EXPECT_THROW((act()), sb::di::NullPointerException); + EXPECT_NO_THROW((act())); } TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) { auto act = [&]() { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::UniquePtrService{nullptr}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::UniquePtrService{nullptr}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; }; EXPECT_THROW((act()), sb::di::InvalidServiceException); @@ -54,36 +54,36 @@ TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) TEST_F(ServiceInstanceListTest, ShouldReturnProperSize) { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; EXPECT_EQ(list.size(), 1); TestClass1 test; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + list.add(sb::di::ServiceInstance{std::move(instance2)}); EXPECT_EQ(list.size(), 2); } TEST_F(ServiceInstanceListTest, ShouldReturnEmpty) { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + list.add(sb::di::ServiceInstance{std::move(instance2)}); EXPECT_FALSE(list.empty()); } TEST_F(ServiceInstanceListTest, ShouldSeal) { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; EXPECT_NO_THROW(list.seal()); EXPECT_TRUE(list.isSealed()); @@ -91,30 +91,30 @@ TEST_F(ServiceInstanceListTest, ShouldSeal) TEST_F(ServiceInstanceListTest, ShouldGetFirst) { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; const auto firstServicePtr = service.get(); - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + list.add(sb::di::ServiceInstance{std::move(instance2)}); - EXPECT_EQ(list.first().get(), firstServicePtr); + EXPECT_EQ(&list.first().getImplementation(), firstServicePtr); } TEST_F(ServiceInstanceListTest, ShouldGetLast) { - sb::di::ServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{std::move(service)}; + sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; const auto lastServicePtr = instance2.get(); - list.add(std::move(instance2)); + list.add(sb::di::ServiceInstance{std::move(instance2)}); - EXPECT_EQ(list.last().get(), lastServicePtr); + EXPECT_EQ(&list.last().getImplementation(), lastServicePtr); } diff --git a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp index dd6067d..0367cf5 100644 --- a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp +++ b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp @@ -31,8 +31,10 @@ TEST_F(ServiceInstancesMapTest, ShouldInsert) sb::di::details::containers::ServiceInstancesMap map{false}; TestClass1 test; - sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; - auto act = [&] { map.insert(typeid(TestClass1), std::move(instance)); }; + sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + auto act = [&] { + map.insert(typeid(TestClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance)}}); + }; EXPECT_NO_THROW(act()); } @@ -42,10 +44,11 @@ TEST_F(ServiceInstancesMapTest, ShouldCheckEmpty) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance)}}) + .add(sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance2)}}); EXPECT_FALSE(map.empty()); } @@ -55,10 +58,11 @@ TEST_F(ServiceInstancesMapTest, ShouldContainsList) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(instance)}) + .add(sb::di::ServiceInstance{std::move(instance2)}); EXPECT_TRUE(map.contains(typeid(TestInheritClass1))); EXPECT_FALSE(map.contains(typeid(TestInheritClass2))); @@ -69,19 +73,20 @@ TEST_F(ServiceInstancesMapTest, ShouldFindList) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::ServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; TestInheritClass2 test2; - sb::di::ServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), std::move(instance)).add(std::move(instance2)); + sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(instance)}) + .add(sb::di::ServiceInstance{std::move(instance2)}); const auto list = map.findServices(typeid(TestInheritClass1)); EXPECT_TRUE(list); - EXPECT_TRUE(list->first()->isValid()); - EXPECT_EQ(list->first()->get(), &test); - EXPECT_EQ(list->first()->getTypeId(), typeid(TestInheritClass3)); - EXPECT_TRUE(list->last()->isValid()); - EXPECT_EQ(list->last()->get(), &test2); - EXPECT_EQ(list->last()->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(list->first().isValid()); + EXPECT_EQ(list->first().getAs(), &test); + EXPECT_EQ(list->first().getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(list->last().isValid()); + EXPECT_EQ(list->last().getAs(), &test2); + EXPECT_EQ(list->last().getImplementation().getTypeId(), typeid(TestInheritClass2)); } TEST_F(ServiceInstancesMapTest, ShouldDestructInProperOrder) @@ -105,22 +110,26 @@ TEST_F(ServiceInstancesMapTest, ShouldDestructInProperOrder) const auto describer = sb::di::ServiceDescriber::describeSingletonFrom([&] { return std::make_unique>(DestructionOrderCheck{cnt, 4}); }); - map.insert(describer.getServiceTypeId(), describer.getImplementationFactory().createInstance(mock, false)); + map.insert(describer.getServiceTypeId(), + sb::di::ServiceInstance{describer.getImplementationFactory().createInstance(mock, false)}); const auto describer2 = sb::di::ServiceDescriber::describeSingletonFrom([&] { return std::make_unique>(DestructionOrderCheck{cnt, 3}); }); - map.insert(describer2.getServiceTypeId(), describer2.getImplementationFactory().createInstance(mock, false)); + map.insert(describer2.getServiceTypeId(), + sb::di::ServiceInstance{describer2.getImplementationFactory().createInstance(mock, false)}); const auto describer3 = sb::di::ServiceDescriber::describeSingletonFrom([&] { return std::make_unique>(DestructionOrderCheck{cnt, 2}); }); - map.insert(describer3.getServiceTypeId(), describer3.getImplementationFactory().createInstance(mock, false)); + map.insert(describer3.getServiceTypeId(), + sb::di::ServiceInstance{describer3.getImplementationFactory().createInstance(mock, false)}); const auto describer4 = sb::di::ServiceDescriber::describeSingletonFrom([&] { return std::make_unique>(DestructionOrderCheck{cnt, 1}); }); - map.insert(describer4.getServiceTypeId(), describer4.getImplementationFactory().createInstance(mock, false)); + map.insert(describer4.getServiceTypeId(), + sb::di::ServiceInstance{describer4.getImplementationFactory().createInstance(mock, false)}); map.clear(); diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp index 23a010e..1a398ca 100644 --- a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -36,9 +36,9 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstance) const auto instance = creator.createInstance(descriptor, false); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) @@ -48,14 +48,13 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); TestInheritClass5 test; - const sb::di::details::services::ExternalService external{&test}; - + sb::di::ServiceInstance external{ + std::make_unique>(&test)}; const auto instance = creator.createInstanceAlias(descriptor, &external); - EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass3)); } TEST_F(ServiceInstanceCreatorTest, ShouldFailForNullProvider) @@ -106,12 +105,13 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailForCirculatDependency) TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) { - sb::di::details::core::ServiceInstanceCreator creator; - - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); - - TestInheritClass5 *test = nullptr; - const sb::di::details::services::ExternalService external{test}; - - EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); + // sb::di::details::core::ServiceInstanceCreator creator; + // + // const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + // + // TestInheritClass5 *test = nullptr; + // sb::di::ServiceInstance external{ + // std::make_unique>(test)}; + // + // EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); } diff --git a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp index a7cbaf6..8dcdcde 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp @@ -265,7 +265,7 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldGetSelf) provider.init(mock); auto &self = provider.getInstance(typeid(sb::di::ServiceProvider)); - EXPECT_EQ(self.get(), &mock); + EXPECT_EQ(self.getAs(), &mock); } TEST_F(ServiceInstanceProviderRootTest, ShouldGetInstances) @@ -303,11 +303,11 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldGetInstancesInOrder) auto &services = *provider.tryGetInstances(typeid(TestInheritClass1)); EXPECT_EQ(services.size(), 5); - EXPECT_EQ(static_cast(services[0]->get())->number(), 1); - EXPECT_EQ(static_cast(services[1]->get())->number(), 2); - EXPECT_EQ(static_cast(services[2]->get())->number(), 3); - EXPECT_EQ(static_cast(services[3]->get())->number(), 4); - EXPECT_EQ(static_cast(services[4]->get())->number(), 5); + EXPECT_EQ(static_cast(services[0].getAs())->number(), 1); + EXPECT_EQ(static_cast(services[1].getAs())->number(), 2); + EXPECT_EQ(static_cast(services[2].getAs())->number(), 3); + EXPECT_EQ(static_cast(services[3].getAs())->number(), 4); + EXPECT_EQ(static_cast(services[4].getAs())->number(), 5); EXPECT_FALSE(provider.tryGetInstances(typeid(TestInheritClass5))); EXPECT_FALSE(provider.tryGetInstances(typeid(TestInheritClass4))); } @@ -329,11 +329,11 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldGetAliasInstancesInOrder) auto &services = *provider.tryGetInstances(typeid(TestInheritClass1)); EXPECT_EQ(services.size(), 5); - EXPECT_EQ(static_cast(services[0]->get())->number(), 2); - EXPECT_EQ(static_cast(services[1]->get())->number(), 3); - EXPECT_EQ(static_cast(services[2]->get())->number(), 4); - EXPECT_EQ(static_cast(services[3]->get())->number(), 5); - EXPECT_EQ(static_cast(services[4]->get())->number(), 6); + EXPECT_EQ(static_cast(services[0].getAs())->number(), 2); + EXPECT_EQ(static_cast(services[1].getAs())->number(), 3); + EXPECT_EQ(static_cast(services[2].getAs())->number(), 4); + EXPECT_EQ(static_cast(services[3].getAs())->number(), 5); + EXPECT_EQ(static_cast(services[4].getAs())->number(), 6); } TEST_F(ServiceInstanceProviderRootTest, ShouldTryCreateInstance) @@ -502,11 +502,11 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldCreateInstancesInOrder) auto services = *provider.tryCreateInstances(typeid(TestInheritClass1)); EXPECT_EQ(services.size(), 5); - EXPECT_EQ(static_cast(services[0]->get())->number(), 1); - EXPECT_EQ(static_cast(services[1]->get())->number(), 2); - EXPECT_EQ(static_cast(services[2]->get())->number(), 3); - EXPECT_EQ(static_cast(services[3]->get())->number(), 4); - EXPECT_EQ(static_cast(services[4]->get())->number(), 5); + EXPECT_EQ(static_cast(services[0].getAs())->number(), 1); + EXPECT_EQ(static_cast(services[1].getAs())->number(), 2); + EXPECT_EQ(static_cast(services[2].getAs())->number(), 3); + EXPECT_EQ(static_cast(services[3].getAs())->number(), 4); + EXPECT_EQ(static_cast(services[4].getAs())->number(), 5); EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass5))); EXPECT_FALSE(provider.tryCreateInstances(typeid(TestInheritClass6))); } @@ -528,9 +528,9 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldCreateAliasInstancesInOrder) auto services = *provider.tryCreateInstances(typeid(TestInheritClass1)); EXPECT_EQ(services.size(), 5); - EXPECT_EQ(static_cast(services[0]->get())->number(), 2); - EXPECT_EQ(static_cast(services[1]->get())->number(), 3); - EXPECT_EQ(static_cast(services[2]->get())->number(), 4); - EXPECT_EQ(static_cast(services[3]->get())->number(), 5); - EXPECT_EQ(static_cast(services[4]->get())->number(), 6); + EXPECT_EQ(static_cast(services[0].getAs())->number(), 2); + EXPECT_EQ(static_cast(services[1].getAs())->number(), 3); + EXPECT_EQ(static_cast(services[2].getAs())->number(), 4); + EXPECT_EQ(static_cast(services[3].getAs())->number(), 5); + EXPECT_EQ(static_cast(services[4].getAs())->number(), 6); } diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp index 9bf694b..bf06b73 100644 --- a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -39,9 +39,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstance) const auto instance = resolver.createInstance(); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstance) @@ -59,9 +59,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstance) const auto instance = resolver.createInstance(); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstance) @@ -78,9 +78,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstance) EXPECT_EQ(instances.size(), 1); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstance) @@ -99,9 +99,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstance) EXPECT_EQ(instances.size(), 1); EXPECT_FALSE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstances) @@ -118,9 +118,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstances) EXPECT_EQ(instances.size(), 1); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstances) @@ -139,15 +139,15 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstances) EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstances) @@ -163,20 +163,20 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstances) const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; sb::di::details::containers::ServiceInstanceList instances{ - descriptors.last().getImplementationFactory().createInstance(mock, false)}; + sb::di::ServiceInstance{descriptors.last().getImplementationFactory().createInstance(mock, false)}}; resolver.createRestInstances(instances); EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceInPlace) @@ -192,9 +192,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceInPlace) const auto instance = resolver.createInstanceInPlace(); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstanceInPlace) @@ -212,9 +212,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstanceInPlace) const auto instance = resolver.createInstanceInPlace(); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstanceInPlace) @@ -231,9 +231,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstanceInPlace) EXPECT_EQ(instances.size(), 1); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstanceInPlace) @@ -252,9 +252,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstanceInPlace) EXPECT_EQ(instances.size(), 1); EXPECT_FALSE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstancesInPlace) @@ -271,9 +271,9 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstancesInPlace) EXPECT_EQ(instances.size(), 1); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestClass1)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstancesInPlace) @@ -292,15 +292,15 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstancesInPlace) EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstancesInPlace) @@ -316,20 +316,20 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstancesInPlace) const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; sb::di::details::containers::ServiceInstanceList instances{ - descriptors.last().getImplementationFactory().createInstance(mock, true)}; + sb::di::ServiceInstance{descriptors.last().getImplementationFactory().createInstance(mock, true)}}; resolver.createRestInstancesInPlace(instances); EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass3)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass5)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass4)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) @@ -345,13 +345,15 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; TestInheritClass6 test; - const sb::di::details::services::ExternalService external(&test); + sb::di::ServiceInstance external{ + std::make_unique>(&test)}; + const auto instance = resolver.createAlias(external); EXPECT_TRUE(instance); - EXPECT_TRUE(instance->isValid()); - EXPECT_TRUE(instance->get()); - EXPECT_EQ(instance->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.getAs()); + EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass5)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneAlias) @@ -367,14 +369,16 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneAlias) const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; TestInheritClass6 test; - const sb::di::details::services::ExternalService external(&test); + sb::di::ServiceInstance external{ + std::make_unique>(&test)}; + const auto instances = resolver.createOneAlias(external); EXPECT_EQ(instances.size(), 1); EXPECT_FALSE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass5)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass5)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllAliases) @@ -390,24 +394,26 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllAliases) TestInheritClass3 test3; TestInheritClass4 test4; TestInheritClass5 test5; - sb::di::details::containers::ServiceInstanceList externals{ - std::make_unique>(&test3)}; - externals.add(std::make_unique>(&test4)); - externals.add(std::make_unique>(&test5)); + sb::di::details::containers::ServiceInstanceList externals{sb::di::ServiceInstance{ + std::make_unique>(&test3)}}; + externals.add(sb::di::ServiceInstance{ + std::make_unique>(&test4)}); + externals.add(sb::di::ServiceInstance{ + std::make_unique>(&test5)}); const auto instances = resolver.createAllAliases(externals.getInnerList()); EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass2)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass2)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass2)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestAliases) @@ -423,25 +429,27 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestAliases) TestInheritClass3 test3; TestInheritClass4 test4; TestInheritClass5 test5; - sb::di::details::containers::ServiceInstanceList externals{ - std::make_unique>(&test3)}; - externals.add(std::make_unique>(&test4)); - externals.add(std::make_unique>(&test5)); + sb::di::details::containers::ServiceInstanceList externals{sb::di::ServiceInstance{ + std::make_unique>(&test3)}}; + externals.add(sb::di::ServiceInstance{ + std::make_unique>(&test4)}); + externals.add(sb::di::ServiceInstance{ + std::make_unique>(&test5)}); - sb::di::details::containers::ServiceInstanceList instances{ - std::make_unique>(&test5)}; + sb::di::details::containers::ServiceInstanceList instances{sb::di::ServiceInstance{ + std::make_unique>(&test5)}}; auto &_ = resolver.createRestAliases(externals.getInnerList(), instances); EXPECT_EQ(instances.size(), 3); EXPECT_TRUE(instances.isSealed()); - EXPECT_TRUE(instances.getInnerList()[0]->isValid()); - EXPECT_TRUE(instances.getInnerList()[0]->get()); - EXPECT_EQ(instances.getInnerList()[0]->getTypeId(), typeid(TestInheritClass2)); - EXPECT_TRUE(instances.getInnerList()[1]->isValid()); - EXPECT_TRUE(instances.getInnerList()[1]->get()); - EXPECT_EQ(instances.getInnerList()[1]->getTypeId(), typeid(TestInheritClass2)); - EXPECT_TRUE(instances.getInnerList()[2]->isValid()); - EXPECT_TRUE(instances.getInnerList()[2]->get()); - EXPECT_EQ(instances.getInnerList()[2]->getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[0].isValid()); + EXPECT_TRUE(instances.getInnerList()[0].getAs()); + EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[1].isValid()); + EXPECT_TRUE(instances.getInnerList()[1].getAs()); + EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_TRUE(instances.getInnerList()[2].isValid()); + EXPECT_TRUE(instances.getInnerList()[2].getAs()); + EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass2)); } diff --git a/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp b/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp index 282df4c..5b55cc2 100644 --- a/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp @@ -33,8 +33,6 @@ TEST_F(ExternalServiceFactoryTest, ShouldCreateService) EXPECT_TRUE(instance->isValid()); EXPECT_EQ(instance->get(), &test); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ExternalServiceFactoryTest, ShouldCreateInPlaceService) @@ -49,8 +47,6 @@ TEST_F(ExternalServiceFactoryTest, ShouldCreateInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_EQ(instance->get(), &test); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ExternalServiceFactoryTest, ShouldCreateNullService) @@ -64,8 +60,6 @@ TEST_F(ExternalServiceFactoryTest, ShouldCreateNullService) EXPECT_FALSE(instance->isValid()); EXPECT_FALSE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ExternalServiceFactoryTest, ShouldCreateNullInPlaceService) @@ -79,6 +73,4 @@ TEST_F(ExternalServiceFactoryTest, ShouldCreateNullInPlaceService) EXPECT_FALSE(instance->isValid()); EXPECT_FALSE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } diff --git a/Tests/Unit/Factories/ServiceFactoryTest.cpp b/Tests/Unit/Factories/ServiceFactoryTest.cpp index 6be3b4b..87951f3 100644 --- a/Tests/Unit/Factories/ServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFactoryTest.cpp @@ -34,8 +34,6 @@ TEST_F(ServiceFactoryTest, ShouldCreateService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateInPlaceService) @@ -49,14 +47,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyInPlaceService) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), createInstanceInPlace(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -69,14 +65,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyInPlaceClass)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -89,14 +83,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -109,14 +101,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr3Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -129,14 +119,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr3Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass3)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr4Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -149,14 +137,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyPtr4Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass4)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyRef1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -169,14 +155,12 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyRef1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyRefClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyRef2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -189,15 +173,14 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyRef2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyRefClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyUniq1Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -211,15 +194,14 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyUniq1Service) EXPECT_TRUE(instance->get()); EXPECT_TRUE( dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyUniq2Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -233,15 +215,14 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyUniq2Service) EXPECT_TRUE(instance->get()); EXPECT_TRUE( dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec1Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -254,15 +235,14 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec2Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -275,16 +255,15 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec3Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -297,16 +276,16 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec3Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass3)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec4Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -319,6 +298,4 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec4Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index 1b6553d..972f5b4 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -34,8 +34,6 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateWithInPlaceService) @@ -49,8 +47,6 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateWithInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateInPlaceService) @@ -64,15 +60,13 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyInPlaceService) { ServiceProviderMock mock; + sb::di::ServiceInstance test1{std::make_unique>()}; - auto test1 = std::make_unique>(); EXPECT_CALL(mock.getMock(), createInstanceInPlace(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -85,14 +79,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyInPlaceService) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyInPlaceClass)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -106,14 +98,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -127,14 +117,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr3Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -148,14 +136,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr3Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass3)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr4Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -169,14 +155,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyPtr4Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyPtrClass4)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyRef1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -190,14 +174,12 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyRef1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyRefClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyRef2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -211,15 +193,14 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyRef2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyRefClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq1Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -234,15 +215,14 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq1Service) EXPECT_TRUE(instance->get()); EXPECT_TRUE( dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq2Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -258,15 +238,14 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyUniq2Service) EXPECT_TRUE(instance->get()); EXPECT_TRUE( dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyUniquePtrClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec1Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -280,15 +259,13 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec1Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass1)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -303,16 +280,15 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass2)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec3Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -326,16 +302,16 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec3Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass3)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -351,6 +327,4 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) EXPECT_TRUE(instance->isValid()); EXPECT_TRUE(instance->get()); EXPECT_TRUE(dynamic_cast *>(instance.get())); - EXPECT_EQ(factory.getServiceTypeId(), typeid(TestDependencyVecClass4)); - EXPECT_EQ(instance->getTypeId(), factory.getServiceTypeId()); } diff --git a/Tests/Unit/Factories/VoidServiceFactoryTest.cpp b/Tests/Unit/Factories/VoidServiceFactoryTest.cpp deleted file mode 100644 index 7a2afe1..0000000 --- a/Tests/Unit/Factories/VoidServiceFactoryTest.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "../../Helpers/Classes/Basic.hpp" -#include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Factories/VoidServiceFactory.hpp" -#include "SevenBit/DI/Exceptions.hpp" - -class VoidServiceFactoryTest : public testing::Test -{ - protected: - static void TearUpTestSuite() {} - - VoidServiceFactoryTest() {} - - void SetUp() override {} - - void TearDown() override {} - - ~VoidServiceFactoryTest() override = default; - - static void TearDownTestSuite() {} -}; - -TEST_F(VoidServiceFactoryTest, ShouldCreateVoidService) -{ - TestClass1 test; - ServiceProviderMock mock; - const sb::di::details::factories::VoidServiceFactory factory{}; - - const auto instance = factory.createInstance(mock, false); - - EXPECT_FALSE(instance); -} - -TEST_F(VoidServiceFactoryTest, ShouldCreateVoidInPlaceService) -{ - TestClass1 test; - ServiceProviderMock mock; - const sb::di::details::factories::VoidServiceFactory factory{}; - - const auto instance = factory.createInstance(mock, true); - - EXPECT_FALSE(instance); -} diff --git a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp index b9c234e..792772b 100644 --- a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp @@ -25,7 +25,7 @@ class ServiceCtorInvokerTest : public testing::Test TEST_F(ServiceCtorInvokerTest, ShouldInvokeFuncWithCtorParams) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); diff --git a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp index e138a34..514c919 100644 --- a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp @@ -25,7 +25,7 @@ class ServiceFactoryInvokerTest : public testing::Test TEST_F(ServiceFactoryInvokerTest, ShouldInvokeFuncFactory) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); diff --git a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp index c577465..c98a951 100644 --- a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp +++ b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp @@ -27,7 +27,7 @@ class ServiceParamProviderTest : public testing::Test TEST_F(ServiceParamProviderTest, ShouldGetDependencyInPlaceService) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), createInstanceInPlace(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -43,7 +43,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyInPlaceService) TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -59,7 +59,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr1Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -75,7 +75,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr2Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr3Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -91,7 +91,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr3Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr4Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); @@ -107,7 +107,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyPtr4Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyRef1Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -123,7 +123,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyRef1Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyRef2Service) { ServiceProviderMock mock; - sb::di::details::services::InPlaceService test1; + sb::di::ServiceInstance test1{std::make_unique>()}; EXPECT_CALL(mock.getMock(), getInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::ReturnRef(test1)); @@ -140,7 +140,8 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyUniq1Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -157,7 +158,8 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyUniq2Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; EXPECT_CALL(mock.getMock(), createInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::move(test1))); @@ -173,8 +175,9 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyUniq2Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec1Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -190,8 +193,8 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec1Service) TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec2Service) { ServiceProviderMock mock; - auto test1 = std::make_unique>(); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{std::make_unique>()}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -208,8 +211,9 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec3Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -227,8 +231,10 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec4Service) { ServiceProviderMock mock; auto service = std::make_unique(); - auto test1 = std::make_unique>(std::move(service)); - sb::di::OneOrList result{std::move(test1)}; + sb::di::ServiceInstance test1{ + std::make_unique>(std::move(service))}; + + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 5c5bacb..2571426 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -28,28 +28,29 @@ TEST_F(ServiceDescriptorTest, ShouldConstructDescriptor) { auto factory = std::make_unique>(); auto act = [&] { - sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory)}; + sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), std::move(factory)}; }; EXPECT_NO_THROW(act()); } -TEST_F(ServiceDescriptorTest, ShouldFailConstructDescriptor) +TEST_F(ServiceDescriptorTest, ShouldNotFailConstructNullFactoryDescriptor) { auto act = [&] { - sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), nullptr}; + sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), nullptr}; }; - EXPECT_THROW(act(), sb::di::NullPointerException); + EXPECT_NO_THROW(act()); } TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromDescriptor) { auto factory = std::make_unique>(); const auto factoryPtr = factory.get(); - const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory)}; + const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), std::move(factory)}; EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); @@ -60,27 +61,26 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromDescriptor) TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) { - auto factory = std::make_unique>(); - const auto factoryPtr = factory.get(); - const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory), 0, true}; + const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), nullptr}; EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); - EXPECT_EQ(&descriptor.getImplementationFactory(), factoryPtr); EXPECT_TRUE(descriptor.isAlias()); + auto getFactory = [&] { auto &f = descriptor.getImplementationFactory(); }; + EXPECT_THROW((getFactory()), sb::di::NullPointerException); } TEST_F(ServiceDescriptorTest, ShouldCompareDescriptors) { auto factory = std::make_unique>(); - const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory)}; + const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), std::move(factory)}; auto factory2 = std::make_unique>(); - const sb::di::ServiceDescriptor descriptor2{typeid(TestClass1), sb::di::ServiceLifeTime::singleton(), - std::move(factory2)}; + const sb::di::ServiceDescriptor descriptor2{typeid(TestClass1), typeid(TestClass1), + sb::di::ServiceLifeTime::singleton(), std::move(factory2)}; const auto &descriptorCopy = descriptor; EXPECT_EQ(descriptor, descriptorCopy); diff --git a/Tests/Unit/Services/AliasServiceTest.cpp b/Tests/Unit/Services/AliasServiceTest.cpp index 20c5a0f..80e8361 100644 --- a/Tests/Unit/Services/AliasServiceTest.cpp +++ b/Tests/Unit/Services/AliasServiceTest.cpp @@ -25,7 +25,6 @@ TEST_F(AliasServiceTest, ShouldCreateExternalService) TestClass1 test; const sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); EXPECT_EQ(service.get(), &test); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -36,9 +35,8 @@ TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalService) TestClass1 test; sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); + EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } TEST_F(AliasServiceTest, ShouldFailMoveOutExternalService) @@ -46,16 +44,14 @@ TEST_F(AliasServiceTest, ShouldFailMoveOutExternalService) TestClass1 test; sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); + EXPECT_THROW(service.getForMoveOut(), sb::di::CannotMoveOutServiceException); } TEST_F(AliasServiceTest, ShouldCreateExternalNullService) { sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); EXPECT_FALSE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -65,16 +61,14 @@ TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) { sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); + EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } TEST_F(AliasServiceTest, ShouldFailMoveOutExternalNullService) { sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); + EXPECT_THROW(service.getForMoveOut(), sb::di::CannotMoveOutServiceException); } diff --git a/Tests/Unit/Services/ExternalServiceTest.cpp b/Tests/Unit/Services/ExternalServiceTest.cpp index a36cf34..50faa64 100644 --- a/Tests/Unit/Services/ExternalServiceTest.cpp +++ b/Tests/Unit/Services/ExternalServiceTest.cpp @@ -25,7 +25,6 @@ TEST_F(ExternalServiceTest, ShouldCreateExternalService) TestClass1 test; const sb::di::details::services::ExternalService service{&test}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); EXPECT_EQ(service.get(), &test); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -36,9 +35,8 @@ TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalService) TestClass1 test; sb::di::details::services::ExternalService service{&test}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); + EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalService) @@ -46,9 +44,8 @@ TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalService) TestClass1 test; sb::di::details::services::ExternalService service{&test}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); + EXPECT_THROW(service.getForMoveOut(), sb::di::CannotMoveOutServiceException); } TEST_F(ExternalServiceTest, ShouldCreateExternalNullService) @@ -56,7 +53,6 @@ TEST_F(ExternalServiceTest, ShouldCreateExternalNullService) TestClass1 test; const sb::di::details::services::ExternalService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); EXPECT_FALSE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -67,9 +63,8 @@ TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) TestClass1 test; sb::di::details::services::ExternalService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); + EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalNullService) @@ -77,7 +72,6 @@ TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalNullService) TestClass1 test; sb::di::details::services::ExternalService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_THROW(service.moveOutAs(), sb::di::CannotMoveOutServiceException); + EXPECT_THROW(service.getForMoveOut(), sb::di::CannotMoveOutServiceException); } diff --git a/Tests/Unit/Services/InPlaceServiceTest.cpp b/Tests/Unit/Services/InPlaceServiceTest.cpp index eb727f3..4799a3e 100644 --- a/Tests/Unit/Services/InPlaceServiceTest.cpp +++ b/Tests/Unit/Services/InPlaceServiceTest.cpp @@ -25,7 +25,6 @@ TEST_F(InPlaceServiceTest, ShouldCreateInPlaceService) { const sb::di::details::services::InPlaceService service{}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); EXPECT_TRUE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -36,9 +35,8 @@ TEST_F(InPlaceServiceTest, ShouldFailMoveAsUniquePtrInPlaceService) TestClass1 test; sb::di::details::services::InPlaceService service{}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_THROW(service.moveOutAsUniquePtr(), sb::di::CannotReleaseServiceException); + EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); EXPECT_TRUE(service.isValid()); } @@ -47,8 +45,7 @@ TEST_F(InPlaceServiceTest, ShouldSuccedMoveOutInPlaceService) TestClass1 test; sb::di::details::services::InPlaceService service{}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_NO_THROW(service.moveOutAs()); + EXPECT_NO_THROW(service.getForMoveOut()); EXPECT_TRUE(service.isValid()); } diff --git a/Tests/Unit/Services/UniquePtrServiceTest.cpp b/Tests/Unit/Services/UniquePtrServiceTest.cpp index b024001..825c647 100644 --- a/Tests/Unit/Services/UniquePtrServiceTest.cpp +++ b/Tests/Unit/Services/UniquePtrServiceTest.cpp @@ -25,7 +25,6 @@ TEST_F(UniquePtrServiceTest, ShouldCreateUniquePtrService) { const sb::di::details::services::UniquePtrService service{std::make_unique()}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); EXPECT_TRUE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -36,10 +35,11 @@ TEST_F(UniquePtrServiceTest, ShouldSuccedMoveAsUniquePtrUniquePtrService) TestClass1 test; sb::di::details::services::UniquePtrService service{std::make_unique()}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_TRUE(service.moveOutAsUniquePtr()); + const auto ptr = static_cast(service.release()); + EXPECT_TRUE(ptr); EXPECT_FALSE(service.isValid()); + delete ptr; } TEST_F(UniquePtrServiceTest, ShouldSuccedMoveOutUniquePtrService) @@ -47,9 +47,8 @@ TEST_F(UniquePtrServiceTest, ShouldSuccedMoveOutUniquePtrService) TestClass1 test; sb::di::details::services::UniquePtrService service{std::make_unique()}; - EXPECT_TRUE(service); EXPECT_TRUE(service.isValid()); - EXPECT_NO_THROW(service.moveOutAs()); + EXPECT_NO_THROW(service.getForMoveOut()); EXPECT_TRUE(service.isValid()); } @@ -57,7 +56,6 @@ TEST_F(UniquePtrServiceTest, ShouldCreateExternalNullService) { const sb::di::details::services::UniquePtrService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); EXPECT_FALSE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); @@ -68,9 +66,8 @@ TEST_F(UniquePtrServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) TestClass1 test; sb::di::details::services::UniquePtrService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_FALSE(service.moveOutAsUniquePtr()); + EXPECT_FALSE(service.getForMoveOut()); EXPECT_FALSE(service.isValid()); } @@ -79,8 +76,7 @@ TEST_F(UniquePtrServiceTest, ShouldFailMoveOutExternalNullService) TestClass1 test; sb::di::details::services::UniquePtrService service{nullptr}; - EXPECT_FALSE(service); EXPECT_FALSE(service.isValid()); - EXPECT_NO_THROW(service.moveOutAs()); + EXPECT_NO_THROW(service.release()); EXPECT_FALSE(service.isValid()); } diff --git a/Tests/Unit/Utils/CheckTest.cpp b/Tests/Unit/Utils/CheckTest.cpp index f72b9d3..b48f62c 100644 --- a/Tests/Unit/Utils/CheckTest.cpp +++ b/Tests/Unit/Utils/CheckTest.cpp @@ -53,19 +53,3 @@ TEST_F(CheckTest, ShouldCheckEnum) EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::B)); EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::C)); } - -TEST_F(CheckTest, ShouldCheckInstanceValidity) -{ - TestClass1 test; - EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity(nullptr)); - EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity( - std::make_unique>(nullptr))); - EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity( - std::make_unique>(&test))); - EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity( - std::make_unique>(nullptr))); - EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity( - std::make_unique>(std::make_unique()))); - EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity( - std::make_unique>())); -} diff --git a/Tests/Unit/Utils/RequireTest.cpp b/Tests/Unit/Utils/RequireTest.cpp index 7031493..8eb1581 100644 --- a/Tests/Unit/Utils/RequireTest.cpp +++ b/Tests/Unit/Utils/RequireTest.cpp @@ -67,21 +67,3 @@ TEST_F(RequireTest, ShouldRequireValidEnum) EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::B)); EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::C)); } - -TEST_F(RequireTest, ShoulRequireValidInstance) -{ - TestClass1 test; - EXPECT_THROW(sb::di::details::utils::Require::validInstance(nullptr), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::validInstance( - std::make_unique>(nullptr)), - sb::di::InvalidServiceException); - EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance( - std::make_unique>(&test))); - EXPECT_THROW(sb::di::details::utils::Require::validInstance( - std::make_unique>(nullptr)), - sb::di::InvalidServiceException); - EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance( - std::make_unique>(std::make_unique()))); - EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance( - std::make_unique>())); -} From 89eef4cbdd411c6f77371f0d691ba3852e70e45e Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sat, 3 Feb 2024 17:14:50 +0100 Subject: [PATCH 33/45] add export --- Include/SevenBit/DI/ServiceInstance.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/SevenBit/DI/ServiceInstance.hpp b/Include/SevenBit/DI/ServiceInstance.hpp index f84b575..ffb492e 100644 --- a/Include/SevenBit/DI/ServiceInstance.hpp +++ b/Include/SevenBit/DI/ServiceInstance.hpp @@ -8,7 +8,7 @@ namespace sb::di { - class ServiceInstance + class EXPORT ServiceInstance { IServiceInstance::Ptr _implementation; ptrdiff_t _castOffset = 0; From caf621d08b7fcc02b27ae81ed2fa13265969ffc9 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 4 Feb 2024 17:57:44 +0100 Subject: [PATCH 34/45] refactor and test update --- .../Containers/Impl/ServiceInstanceList.hpp | 10 ++- .../Containers/Impl/ServiceInstancesMap.hpp | 4 +- .../Containers/ServiceInstanceList.hpp | 2 +- .../Containers/ServiceInstancesMap.hpp | 2 +- .../Core/Impl/ServiceInstanceCreator.hpp | 19 +++-- .../Core/Impl/ServiceInstanceProvider.hpp | 10 +-- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 6 ++ .../Details/Core/ServiceInstanceCreator.hpp | 3 + .../Core/ServiceInstanceProviderRoot.hpp | 3 +- Include/SevenBit/DI/Details/Utils/Cast.hpp | 6 +- Include/SevenBit/DI/Details/Utils/Check.hpp | 9 +++ .../SevenBit/DI/Details/Utils/Impl/Check.hpp | 12 +++ .../DI/Details/Utils/Impl/Require.hpp | 38 +++++++++ Include/SevenBit/DI/Details/Utils/Require.hpp | 16 +++- Include/SevenBit/DI/Impl/ServiceInstance.hpp | 34 +++++--- Include/SevenBit/DI/Impl/ServiceProvider.hpp | 35 ++++++++ Include/SevenBit/DI/ServiceInstance.hpp | 6 +- Include/SevenBit/DI/ServiceProvider.hpp | 55 +++++-------- Source/Source.cpp | 3 + .../Containers/ServiceDescriptorListTest.cpp | 22 ++++- .../Containers/ServiceInstanceListTest.cpp | 60 +++++++------- .../Containers/ServiceInstancesMapTest.cpp | 36 ++++----- .../Unit/Core/ServiceInstanceCreatorTest.cpp | 24 +++--- .../Core/ServiceInstanceProviderRootTest.cpp | 22 ++++- .../Unit/Core/ServiceInstanceResolverTest.cpp | 61 +++++++------- Tests/Unit/OneOrListTest.cpp | 26 ++++++ Tests/Unit/ServiceDescriptorTest.cpp | 14 ++-- Tests/Unit/ServiceInstanceTest.cpp | 80 +++++++++++++++++++ Tests/Unit/ServiceProviderTest.cpp | 42 ++++++++++ Tests/Unit/Services/AliasServiceTest.cpp | 14 ++-- Tests/Unit/Services/ExternalServiceTest.cpp | 7 +- Tests/Unit/Services/InPlaceServiceTest.cpp | 2 +- Tests/Unit/Services/UniquePtrServiceTest.cpp | 8 +- Tests/Unit/Utils/CastTest.cpp | 59 ++++++++++++++ Tests/Unit/Utils/CheckTest.cpp | 17 ++++ Tests/Unit/Utils/InheritanceTest.cpp | 8 ++ Tests/Unit/Utils/RequireTest.cpp | 20 +++++ 37 files changed, 605 insertions(+), 190 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Utils/Impl/Check.hpp create mode 100644 Include/SevenBit/DI/Details/Utils/Impl/Require.hpp create mode 100644 Include/SevenBit/DI/Impl/ServiceProvider.hpp create mode 100644 Tests/Unit/ServiceInstanceTest.cpp create mode 100644 Tests/Unit/ServiceProviderTest.cpp create mode 100644 Tests/Unit/Utils/CastTest.cpp diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp index 04b5ae6..4d50312 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp @@ -10,9 +10,15 @@ namespace sb::di::details::containers { INLINE ServiceInstanceList::ServiceInstanceList(const size_t size) : _oneOrList(size) {} - INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance instance) : _oneOrList(std::move(instance)) {} + INLINE ServiceInstanceList::ServiceInstanceList(ServiceInstance instance) + : _oneOrList(utils::Require::validInstanceAndGet(std::move(instance))) + { + } - INLINE void ServiceInstanceList::add(ServiceInstance &&service) { _oneOrList.add(std::move(service)); } + INLINE void ServiceInstanceList::add(ServiceInstance &&instance) + { + _oneOrList.add(utils::Require::validInstanceAndGet(std::move(instance))); + } INLINE OneOrList &ServiceInstanceList::getInnerList() { return _oneOrList; } INLINE const OneOrList &ServiceInstanceList::getInnerList() const { return _oneOrList; } diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp index e5958b3..f1a33f7 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstancesMap.hpp @@ -31,7 +31,7 @@ namespace sb::di::details::containers return _serviceListMap.count(serviceTypeId); } - INLINE ServiceInstanceList *ServiceInstancesMap::findServices(const TypeId serviceTypeId) + INLINE ServiceInstanceList *ServiceInstancesMap::findInstances(const TypeId serviceTypeId) { const auto it = _serviceListMap.find(serviceTypeId); return it != _serviceListMap.end() ? &it->second : nullptr; @@ -45,7 +45,7 @@ namespace sb::di::details::containers { for (auto it = _constructionOrder.rbegin(); it != _constructionOrder.rend(); ++it) { - if (const auto list = findServices(*it)) + if (const auto list = findInstances(*it)) { list->clear(); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index 6f29426..72e8bc8 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -24,7 +24,7 @@ namespace sb::di::details::containers ServiceInstanceList &operator=(const ServiceInstanceList &) = delete; ServiceInstanceList &operator=(ServiceInstanceList &&) = default; - void add(ServiceInstance &&service); + void add(ServiceInstance &&instance); [[nodiscard]] auto begin() const { return _oneOrList.getAsList().begin(); } [[nodiscard]] auto end() const { return _oneOrList.getAsList().end(); } diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp index 1c5d15d..affa07f 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp @@ -33,7 +33,7 @@ namespace sb::di::details::containers [[nodiscard]] bool contains(TypeId serviceTypeId) const; - ServiceInstanceList *findServices(TypeId serviceTypeId); + ServiceInstanceList *findInstances(TypeId serviceTypeId); [[nodiscard]] bool empty() const; diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index fa5f5b1..75263cf 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -21,15 +21,24 @@ namespace sb::di::details::core auto &provider = *utils::Require::notNullAndGet(_serviceProvider); auto &factory = descriptor.getImplementationFactory(); auto _ = _guard(descriptor.getImplementationTypeId()); - return ServiceInstance{factory.createInstance(provider, inPlaceRequest), descriptor.getCastOffset()}; + + auto implementation = factory.createInstance(provider, inPlaceRequest); + return createInstance(std::move(implementation), descriptor.getCastOffset()); } INLINE ServiceInstance ServiceInstanceCreator::createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance) { - utils::Require::notNull(instance); - auto aliasInstance = - std::make_unique(instance->getAs(), descriptor.getImplementationTypeId()); - return ServiceInstance{std::move(aliasInstance), descriptor.getCastOffset()}; + utils::Require::validInstance(instance); + auto implementationType = descriptor.getImplementationTypeId(); + + auto implementation = std::make_unique(instance->getAs(), implementationType); + return createInstance(std::move(implementation), descriptor.getCastOffset()); + } + + INLINE ServiceInstance ServiceInstanceCreator::createInstance(IServiceInstance::Ptr implementation, + const ptrdiff_t castOffset) + { + return utils::Require::validInstanceAndGet(ServiceInstance{std::move(implementation), castOffset}); } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 377941a..5c2ed58 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -35,7 +35,7 @@ namespace sb::di::details::core INLINE const ServiceInstance &ServiceInstanceProvider::getInstance(const TypeId serviceTypeId) { - if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::notNull(instance)) + if (const auto instance = tryGetInstance(serviceTypeId); utils::Check::instanceValidity(instance)) { return *instance; } @@ -72,7 +72,7 @@ namespace sb::di::details::core INLINE ServiceInstance ServiceInstanceProvider::createInstance(const TypeId serviceTypeId) { - if (auto instance = tryCreateInstance(serviceTypeId); instance.isValid()) + if (auto instance = tryCreateInstance(serviceTypeId); utils::Check::instanceValidity(instance)) { return instance; } @@ -103,7 +103,7 @@ namespace sb::di::details::core INLINE ServiceInstance ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) { - if (auto instance = tryCreateInstanceInPlace(serviceTypeId); instance.isValid()) + if (auto instance = tryCreateInstanceInPlace(serviceTypeId); utils::Check::instanceValidity(instance)) { return instance; } @@ -126,8 +126,8 @@ namespace sb::di::details::core INLINE containers::ServiceInstanceList *ServiceInstanceProvider::findRegisteredInstances(const TypeId serviceTypeId) { - const auto singletons = _root.getSingletons().findServices(serviceTypeId); - return singletons ? singletons : _scoped.findServices(serviceTypeId); + const auto singletons = _root.getSingletons().findInstances(serviceTypeId); + return singletons ? singletons : _scoped.findInstances(serviceTypeId); } INLINE const containers::ServiceDescriptorList *ServiceInstanceProvider::findDescriptors(const TypeId serviceTypeId, diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index d2756cc..8ea0ea6 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -6,6 +6,12 @@ namespace sb::di::details::core { + INLINE ServiceInstanceProviderRoot::ServiceInstanceProviderRoot(ServiceProviderOptions options) + : ServiceInstanceProvider(*this, options), _descriptorsMap(options.checkServiceGlobalUniqueness), + _singletons(options.strongDestructionOrder) + { + } + INLINE void ServiceInstanceProviderRoot::init(ServiceProvider &serviceProvider) { ServiceInstanceProvider::init(serviceProvider); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index ec0075c..02ab01b 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -18,6 +18,9 @@ namespace sb::di::details::core ServiceInstance createInstance(const ServiceDescriptor &descriptor, bool inPlaceRequest); ServiceInstance createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance); + + private: + ServiceInstance createInstance(IServiceInstance::Ptr implementation, ptrdiff_t castOffset); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index 64b1d1f..ced8f90 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core @@ -21,6 +20,8 @@ namespace sb::di::details::core using Ptr = std::unique_ptr; using SPtr = std::shared_ptr; + explicit ServiceInstanceProviderRoot(ServiceProviderOptions options = {}); + template ServiceInstanceProviderRoot(TDescriptorIt begin, TDescriptorIt end, ServiceProviderOptions options = {}) : ServiceInstanceProvider(*this, options), diff --git a/Include/SevenBit/DI/Details/Utils/Cast.hpp b/Include/SevenBit/DI/Details/Utils/Cast.hpp index bb06eb1..4e79aab 100644 --- a/Include/SevenBit/DI/Details/Utils/Cast.hpp +++ b/Include/SevenBit/DI/Details/Utils/Cast.hpp @@ -9,10 +9,10 @@ namespace sb::di::details::utils { struct Cast { - template static constexpr intptr_t getCastOffset() + template static constexpr intptr_t getCastOffset() { - auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); - auto service = static_cast(implementation); + auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); + auto service = static_cast(implementation); return reinterpret_cast(service) - reinterpret_cast(implementation); }; diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 3263711..571b056 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -2,6 +2,7 @@ #include #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { @@ -17,5 +18,13 @@ namespace sb::di::details::utils { return std::is_enum_v && value >= 0 && value < TEnum::Count; } + + static bool instanceValidity(const ServiceInstance *instance); + + static bool instanceValidity(const ServiceInstance &instance); }; } // namespace sb::di::details::utils + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Utils/Impl/Check.hpp" +#endif diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp new file mode 100644 index 0000000..05b5a98 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/Impl/Check.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Utils/Check.hpp" + +namespace sb::di::details::utils +{ + INLINE bool Check::instanceValidity(const ServiceInstance *instance) { return instance && instance->isValid(); } + + INLINE bool Check::instanceValidity(const ServiceInstance &instance) { return instance.isValid(); } +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp new file mode 100644 index 0000000..738a4e5 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Utils/Require.hpp" + +namespace sb::di::details::utils +{ + INLINE ServiceInstance *Require::validInstanceAndGet(ServiceInstance *instance) + { + validInstance(instance); + return instance; + } + + INLINE ServiceInstance &&Require::validInstanceAndGet(ServiceInstance &&instance) + { + validInstance(instance); + return std::move(instance); + } + + INLINE void Require::validInstance(const ServiceInstance *instance) + { + notNull(instance); + validInstance(*instance); + } + + INLINE void Require::validInstance(const ServiceInstance &instance) + { + if (!instance.isValid()) + { + if (instance.tryGetImplementation()) + { + throw InvalidServiceException{instance.tryGetImplementation()->getTypeId()}; + } + throw InvalidServiceException{}; + } + } +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index 6d07c74..0dc37d1 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -12,14 +12,14 @@ namespace sb::di::details::utils struct EXPORT Require { template - static std::unique_ptr notNullAndGet(std::unique_ptr &&ptr, std::string_view failMessage = "") + static std::unique_ptr &¬NullAndGet(std::unique_ptr &&ptr, std::string_view failMessage = "") { notNull(ptr.get(), failMessage); return std::move(ptr); } template - static std::shared_ptr notNullAndGet(std::shared_ptr &&ptr, std::string_view failMessage = "") + static std::shared_ptr &¬NullAndGet(std::shared_ptr &&ptr, std::string_view failMessage = "") { notNull(ptr.get(), failMessage); return std::move(ptr); @@ -66,5 +66,17 @@ namespace sb::di::details::utils std::to_string(TEnum::Count) + ")"}; } } + + static ServiceInstance *validInstanceAndGet(ServiceInstance *instance); + + static ServiceInstance &&validInstanceAndGet(ServiceInstance &&instance); + + static void validInstance(const ServiceInstance *instance); + + static void validInstance(const ServiceInstance &instance); }; } // namespace sb::di::details::utils + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Details/Utils/Impl/Require.hpp" +#endif diff --git a/Include/SevenBit/DI/Impl/ServiceInstance.hpp b/Include/SevenBit/DI/Impl/ServiceInstance.hpp index 0b42ea1..3a4be9c 100644 --- a/Include/SevenBit/DI/Impl/ServiceInstance.hpp +++ b/Include/SevenBit/DI/Impl/ServiceInstance.hpp @@ -2,45 +2,53 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" + #include "SevenBit/DI/Details/Utils/Cast.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di { INLINE ServiceInstance::ServiceInstance(IServiceInstance::Ptr implementation, const ptrdiff_t castOffset) : _implementation(std::move(implementation)), _castOffset(castOffset) { - details::utils::Require::notNull(_implementation); - if (!_implementation->isValid()) - { - throw InvalidServiceException{_implementation->getTypeId()}; - } } + INLINE IServiceInstance *ServiceInstance::tryGetImplementation() { return _implementation.get(); } + + INLINE const IServiceInstance *ServiceInstance::tryGetImplementation() const { return _implementation.get(); } + INLINE IServiceInstance &ServiceInstance::getImplementation() { - return *details::utils::Require::notNullAndGet(_implementation.get()); + if (!_implementation) + { + throw NullPointerException{"service implementation cannot be null"}; + } + return *_implementation; } INLINE const IServiceInstance &ServiceInstance::getImplementation() const { - return *details::utils::Require::notNullAndGet(_implementation.get()); + if (!_implementation) + { + throw NullPointerException{"service implementation cannot be null"}; + } + return *_implementation; } INLINE void ServiceInstance::addCastOffset(const ptrdiff_t castOffset) { _castOffset += castOffset; } + INLINE void ServiceInstance::setCastOffset(const ptrdiff_t castOffset) { _castOffset = castOffset; } + + INLINE ptrdiff_t ServiceInstance::getCastOffset() const { return _castOffset; } + INLINE bool ServiceInstance::isValid() const { return _implementation && _implementation->isValid(); } INLINE ServiceInstance::operator bool() const { return isValid(); } INLINE void ServiceInstance::clear() { - if (_implementation) - { - _implementation.reset(); - } + _implementation.reset(); _castOffset = 0; } diff --git a/Include/SevenBit/DI/Impl/ServiceProvider.hpp b/Include/SevenBit/DI/Impl/ServiceProvider.hpp new file mode 100644 index 0000000..61ddfaa --- /dev/null +++ b/Include/SevenBit/DI/Impl/ServiceProvider.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/ServiceProvider.hpp" + +namespace sb::di +{ + INLINE ServiceProvider::ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) + : _instanceProvider(std::move(instanceProvider)) + { + details::utils::Require::notNull(_instanceProvider); + getInstanceProvider().init(*this); + } + + INLINE const ServiceProviderOptions &ServiceProvider::getOptions() const + { + return getInstanceProvider().getOptions(); + } + + INLINE ServiceProvider ServiceProvider::createScope() const + { + return ServiceProvider{getInstanceProvider().createScope()}; + } + + INLINE ServiceProvider::Ptr ServiceProvider::createScopeAsPtr() const + { + return std::make_unique(getInstanceProvider().createScope()); + } + + INLINE const IServiceInstanceProvider &ServiceProvider::getInstanceProvider() const { return *_instanceProvider; } + + INLINE IServiceInstanceProvider &ServiceProvider::getInstanceProvider() { return *_instanceProvider; } + +} // namespace sb::di diff --git a/Include/SevenBit/DI/ServiceInstance.hpp b/Include/SevenBit/DI/ServiceInstance.hpp index ffb492e..8af5256 100644 --- a/Include/SevenBit/DI/ServiceInstance.hpp +++ b/Include/SevenBit/DI/ServiceInstance.hpp @@ -26,11 +26,15 @@ namespace sb::di ServiceInstance &operator=(const ServiceInstance &other) = delete; ServiceInstance &operator=(ServiceInstance &&other) = default; - IServiceInstance &getImplementation(); + IServiceInstance *tryGetImplementation(); + [[nodiscard]] const IServiceInstance *tryGetImplementation() const; + IServiceInstance &getImplementation(); [[nodiscard]] const IServiceInstance &getImplementation() const; void addCastOffset(ptrdiff_t castOffset); + void setCastOffset(ptrdiff_t castOffset); + [[nodiscard]] ptrdiff_t getCastOffset() const; /** * @brief Checks if service instance is valid diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index 859c0eb..73c8f0b 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -11,7 +11,7 @@ namespace sb::di { - class ServiceProvider + class EXPORT ServiceProvider { IServiceInstanceProvider::Ptr _instanceProvider; @@ -21,12 +21,7 @@ namespace sb::di /** * @brief Constructs service provider with specified instance provider */ - explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) - : _instanceProvider(std::move(instanceProvider)) - { - details::utils::Require::notNull(_instanceProvider); - getInstanceProvider().init(*this); - } + explicit ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider); ServiceProvider(const ServiceProvider &parent) = delete; ServiceProvider(ServiceProvider &&) = delete; @@ -44,7 +39,7 @@ namespace sb::di * auto& usedOptions = provider.getOptions(); * @endcode */ - [[nodiscard]] const ServiceProviderOptions &getOptions() const { return getInstanceProvider().getOptions(); } + [[nodiscard]] const ServiceProviderOptions &getOptions() const; /** * @brief Create a scoped service provider @@ -58,10 +53,7 @@ namespace sb::di * &scoped.getService() != &provide.getService(); // True * @endcode */ - [[nodiscard]] ServiceProvider createScope() const - { - return ServiceProvider{getInstanceProvider().createScope()}; - } + [[nodiscard]] ServiceProvider createScope() const; /** * @brief Create a scoped service provider as unique_ptr @@ -75,22 +67,18 @@ namespace sb::di * &scoped->getService() != &provider->getService(); // True * @endcode */ - [[nodiscard]] ServiceProvider::Ptr createScopeAsPtr() const - { - return std::make_unique(getInstanceProvider().createScope()); - } - + [[nodiscard]] Ptr createScopeAsPtr() const; /** * @brief Returns inner service instance provider * @throws sb::di::NullPointerException */ - [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const { return *_instanceProvider; } + [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const; /** * @brief Returns inner service instance provider * @throws sb::di::NullPointerException */ - IServiceInstanceProvider &getInstanceProvider() { return *_instanceProvider; } + IServiceInstanceProvider &getInstanceProvider(); /** * @brief Returns service pointer, might be null @@ -106,7 +94,7 @@ namespace sb::di template TService *tryGetService() { if (const auto instance = getInstanceProvider().tryGetInstance(typeid(TService)); - checkInstanceValidity(instance)) + details::utils::Check::instanceValidity(instance)) { return instance->getAs(); } @@ -128,7 +116,7 @@ namespace sb::di template TService &getService() { auto &instance = getInstanceProvider().getInstance(typeid(TService)); - requireValidInstance(instance); + details::utils::Require::validInstance(instance); return *instance.getAs(); } @@ -151,7 +139,7 @@ namespace sb::di if (auto instances = getInstanceProvider().tryGetInstances(typeid(TService))) { return instances->map([&](const ServiceInstance &instance) { - requireValidInstance(instance); + details::utils::Require::validInstance(instance); return instance.getAs(); }); } @@ -172,7 +160,7 @@ namespace sb::di template std::unique_ptr tryCreateService() { if (auto instance = getInstanceProvider().tryCreateInstance(typeid(TService)); - checkInstanceValidity(&instance)) + details::utils::Check::instanceValidity(&instance)) { return instance.moveOutAsUniquePtr(); } @@ -194,7 +182,7 @@ namespace sb::di template std::unique_ptr createService() { auto instance = getInstanceProvider().createInstance(typeid(TService)); - requireValidInstance(instance); + details::utils::Require::validInstance(instance); return instance.moveOutAsUniquePtr(); } @@ -213,7 +201,7 @@ namespace sb::di template TService createServiceInPlace() { auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); - requireValidInstance(instance); + details::utils::Require::validInstance(instance); return instance.moveOutAs(); } @@ -236,22 +224,15 @@ namespace sb::di if (auto instances = getInstanceProvider().tryCreateInstances(typeid(TService))) { return instances->map([&](ServiceInstance &instance) { - requireValidInstance(instance); + details::utils::Require::validInstance(instance); return instance.moveOutAsUniquePtr(); }); } return {}; } - - private: - static bool checkInstanceValidity(const ServiceInstance *instance) { return instance && instance->isValid(); } - - static void requireValidInstance(const ServiceInstance &instance) - { - if (!instance.isValid()) - { - throw InvalidServiceException(); - } - } }; } // namespace sb::di + +#ifdef _7BIT_DI_ADD_IMPL +#include "SevenBit/DI/Impl/ServiceProvider.hpp" +#endif diff --git a/Source/Source.cpp b/Source/Source.cpp index e448b0f..1561253 100644 --- a/Source/Source.cpp +++ b/Source/Source.cpp @@ -11,7 +11,10 @@ #include "SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp" #include "SevenBit/DI/Details/Helpers/Impl/CircularDependencyGuard.hpp" #include "SevenBit/DI/Details/Helpers/Impl/ScopedGuard.hpp" +#include "SevenBit/DI/Details/Utils/Impl/Check.hpp" +#include "SevenBit/DI/Details/Utils/Impl/Require.hpp" #include "SevenBit/DI/Impl/Exceptions.hpp" #include "SevenBit/DI/Impl/ServiceCollection.hpp" #include "SevenBit/DI/Impl/ServiceDescriptor.hpp" #include "SevenBit/DI/Impl/ServiceInstance.hpp" +#include "SevenBit/DI/Impl/ServiceProvider.hpp" diff --git a/Tests/Unit/Containers/ServiceDescriptorListTest.cpp b/Tests/Unit/Containers/ServiceDescriptorListTest.cpp index b185f8f..dd7ecde 100644 --- a/Tests/Unit/Containers/ServiceDescriptorListTest.cpp +++ b/Tests/Unit/Containers/ServiceDescriptorListTest.cpp @@ -47,7 +47,7 @@ TEST_F(ServiceDescriptorListTest, ShouldAddServiceAliasDescriptors) EXPECT_NO_THROW(act()); } -TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch1) +TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch) { sb::di::details::containers::ServiceDescriptorList list( sb::di::ServiceDescriber::describeAlias()); @@ -59,7 +59,7 @@ TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch1) EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); } -TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatch2) +TEST_F(ServiceDescriptorListTest, ShouldFailAddServiceDescriptorAliasMismatchOpposite) { sb::di::details::containers::ServiceDescriptorList list( sb::di::ServiceDescriber::describeSingleton()); @@ -165,3 +165,21 @@ TEST_F(ServiceDescriptorListTest, ShouldGetLast) EXPECT_EQ(list.last(), describedLast); } + +TEST_F(ServiceDescriptorListTest, ShouldGetNotIsAlias) +{ + sb::di::details::containers::ServiceDescriptorList list( + sb::di::ServiceDescriber::describeSingleton()); + list.add(sb::di::ServiceDescriber::describeSingleton()); + + EXPECT_FALSE(list.isAlias()); +} + +TEST_F(ServiceDescriptorListTest, ShouldGetIsAlias) +{ + sb::di::details::containers::ServiceDescriptorList list( + sb::di::ServiceDescriber::describeAlias()); + list.add(sb::di::ServiceDescriber::describeAlias()); + + EXPECT_TRUE(list.isAlias()); +} diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index 0dc7f37..f4f2897 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -28,25 +28,25 @@ class ServiceInstanceListTest : public testing::Test TEST_F(ServiceInstanceListTest, ShouldAddServices) { TestClass1 test; - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::ExternalService{&test}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(&test); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test); + list.add(sb::di::ServiceInstance{std::move(implementation2)}); } -TEST_F(ServiceInstanceListTest, ShouldNotFailAddNullService) +TEST_F(ServiceInstanceListTest, ShouldFailAddNullService) { auto act = [&]() { sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{}}; }; - EXPECT_NO_THROW((act())); + EXPECT_THROW((act()), sb::di::InvalidServiceException); } TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) { auto act = [&]() { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::UniquePtrService{nullptr}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(nullptr); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; }; EXPECT_THROW((act()), sb::di::InvalidServiceException); @@ -54,36 +54,36 @@ TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) TEST_F(ServiceInstanceListTest, ShouldReturnProperSize) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; EXPECT_EQ(list.size(), 1); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test); + list.add(sb::di::ServiceInstance{std::move(implementation2)}); EXPECT_EQ(list.size(), 2); } TEST_F(ServiceInstanceListTest, ShouldReturnEmpty) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test); + list.add(sb::di::ServiceInstance{std::move(implementation2)}); EXPECT_FALSE(list.empty()); } TEST_F(ServiceInstanceListTest, ShouldSeal) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; EXPECT_NO_THROW(list.seal()); EXPECT_TRUE(list.isSealed()); @@ -91,30 +91,30 @@ TEST_F(ServiceInstanceListTest, ShouldSeal) TEST_F(ServiceInstanceListTest, ShouldGetFirst) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - const auto firstServicePtr = service.get(); - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(); + const auto firstServicePtr = implementation.get(); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - list.add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test); + list.add(sb::di::ServiceInstance{std::move(implementation2)}); - EXPECT_EQ(&list.first().getImplementation(), firstServicePtr); + EXPECT_EQ(list.first().tryGetImplementation(), firstServicePtr); } TEST_F(ServiceInstanceListTest, ShouldGetLast) { - sb::di::IServiceInstance::Ptr service{new sb::di::details::services::InPlaceService{}}; - sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(service)}}; + auto implementation = std::make_unique>(); + sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; EXPECT_FALSE(list.empty()); TestClass1 test; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test}}; - const auto lastServicePtr = instance2.get(); - list.add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test); + const auto lastServicePtr = implementation2.get(); + list.add(sb::di::ServiceInstance{std::move(implementation2)}); - EXPECT_EQ(&list.last().getImplementation(), lastServicePtr); + EXPECT_EQ(list.last().tryGetImplementation(), lastServicePtr); } diff --git a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp index 0367cf5..32646b1 100644 --- a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp +++ b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp @@ -31,9 +31,9 @@ TEST_F(ServiceInstancesMapTest, ShouldInsert) sb::di::details::containers::ServiceInstancesMap map{false}; TestClass1 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + auto implementation = std::make_unique>(&test); auto act = [&] { - map.insert(typeid(TestClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance)}}); + map.insert(typeid(TestClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(implementation)}}); }; EXPECT_NO_THROW(act()); @@ -44,11 +44,11 @@ TEST_F(ServiceInstancesMapTest, ShouldCheckEmpty) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + auto implementation = std::make_unique>(&test); TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance)}}) - .add(sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(instance2)}}); + auto implementation2 = std::make_unique>(&test2); + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(implementation)}}) + .add(sb::di::ServiceInstance{sb::di::ServiceInstance{std::move(implementation2)}}); EXPECT_FALSE(map.empty()); } @@ -58,35 +58,35 @@ TEST_F(ServiceInstancesMapTest, ShouldContainsList) sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + auto implementation = std::make_unique>(&test); TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(instance)}) - .add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test2); + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(implementation)}) + .add(sb::di::ServiceInstance{std::move(implementation2)}); EXPECT_TRUE(map.contains(typeid(TestInheritClass1))); EXPECT_FALSE(map.contains(typeid(TestInheritClass2))); } -TEST_F(ServiceInstancesMapTest, ShouldFindList) +TEST_F(ServiceInstancesMapTest, ShouldFindInstances) { sb::di::details::containers::ServiceInstancesMap map{false}; TestInheritClass3 test; - sb::di::IServiceInstance::Ptr instance{new sb::di::details::services::ExternalService{&test}}; + auto implementation = std::make_unique>(&test); TestInheritClass2 test2; - sb::di::IServiceInstance::Ptr instance2{new sb::di::details::services::ExternalService{&test2}}; - map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(instance)}) - .add(sb::di::ServiceInstance{std::move(instance2)}); + auto implementation2 = std::make_unique>(&test2); + map.insert(typeid(TestInheritClass1), sb::di::ServiceInstance{std::move(implementation)}) + .add(sb::di::ServiceInstance{std::move(implementation2)}); - const auto list = map.findServices(typeid(TestInheritClass1)); + const auto list = map.findInstances(typeid(TestInheritClass1)); EXPECT_TRUE(list); EXPECT_TRUE(list->first().isValid()); EXPECT_EQ(list->first().getAs(), &test); - EXPECT_EQ(list->first().getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(list->first().tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); EXPECT_TRUE(list->last().isValid()); EXPECT_EQ(list->last().getAs(), &test2); - EXPECT_EQ(list->last().getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(list->last().tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); } TEST_F(ServiceInstancesMapTest, ShouldDestructInProperOrder) diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp index 1a398ca..63bccdd 100644 --- a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -38,7 +38,7 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstance) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) @@ -48,13 +48,13 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); TestInheritClass5 test; - sb::di::ServiceInstance external{ + const sb::di::ServiceInstance external{ std::make_unique>(&test)}; const auto instance = creator.createInstanceAlias(descriptor, &external); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); } TEST_F(ServiceInstanceCreatorTest, ShouldFailForNullProvider) @@ -105,13 +105,13 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailForCirculatDependency) TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) { - // sb::di::details::core::ServiceInstanceCreator creator; - // - // const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); - // - // TestInheritClass5 *test = nullptr; - // sb::di::ServiceInstance external{ - // std::make_unique>(test)}; - // - // EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 *test = nullptr; + const sb::di::ServiceInstance external{ + std::make_unique>(test)}; + + EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); } diff --git a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp index 8dcdcde..dc8c772 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp @@ -92,7 +92,7 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAliasMissmatchI EXPECT_THROW(act(), sb::di::ServiceAliasMismatchException); } -TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAliasMissmatchInheritedService2) +TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToAliasMissmatchOpositeInheritedService) { ServiceProviderMock mock; std::vector describers; @@ -166,6 +166,26 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldFailGetServiceDueToLifetimeMissmat EXPECT_THROW(act(), sb::di::ServiceLifeTimeMismatchException); } +TEST_F(ServiceInstanceProviderRootTest, ShouldPrebuildSingletons) +{ + ServiceProviderMock mock; + std::vector describers; + + describers.emplace_back(sb::di::ServiceDescriber::describeSingleton()); + describers.emplace_back(sb::di::ServiceDescriber::describeScoped()); + describers.emplace_back(sb::di::ServiceDescriber::describeTransient()); + + sb::di::ServiceProviderOptions options; + options.prebuildSingletons = true; + sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end(), options); + provider.init(mock); + + EXPECT_TRUE(provider.tryGetInstance(typeid(TestClass1))); + EXPECT_TRUE(provider.tryGetInstance(typeid(TestClass2))); + EXPECT_FALSE(provider.tryGetInstance(typeid(TestClass3))); + EXPECT_FALSE(provider.tryGetInstance(typeid(TestClass4))); +} + TEST_F(ServiceInstanceProviderRootTest, ShouldTryGetInstance) { ServiceProviderMock mock; diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp index bf06b73..5bcc836 100644 --- a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -2,7 +2,6 @@ #include #include "../../Helpers/Classes/Basic.hpp" -#include "../../Helpers/Classes/CirularDependency.hpp" #include "../../Helpers/Classes/Inherit.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" @@ -41,7 +40,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstance) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstance) @@ -61,7 +60,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstance) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstance) @@ -80,7 +79,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstance) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstance) @@ -101,7 +100,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstance) EXPECT_FALSE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstances) @@ -120,7 +119,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstances) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstances) @@ -141,13 +140,13 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstances) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstances) @@ -170,13 +169,13 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstances) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceInPlace) @@ -194,7 +193,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInstanceInPlace) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstanceInPlace) @@ -214,7 +213,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateInheritedInstanceInPlace) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstanceInPlace) @@ -233,7 +232,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInstanceInPlace) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstanceInPlace) @@ -254,7 +253,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneInheritedInstanceInPlace) EXPECT_FALSE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstancesInPlace) @@ -273,7 +272,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInstancesInPlace) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestClass1)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestClass1)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstancesInPlace) @@ -294,13 +293,13 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllInheritedInstancesInPlace) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstancesInPlace) @@ -323,13 +322,13 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestInheritedInstancesInPlace) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass4)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass4)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) @@ -353,7 +352,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) EXPECT_TRUE(instance); EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateOneAlias) @@ -378,7 +377,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateOneAlias) EXPECT_FALSE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass5)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateAllAliases) @@ -407,13 +406,13 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAllAliases) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); } TEST_F(ServiceInstanceResolverTest, ShouldCreateRestAliases) @@ -445,11 +444,11 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateRestAliases) EXPECT_TRUE(instances.isSealed()); EXPECT_TRUE(instances.getInnerList()[0].isValid()); EXPECT_TRUE(instances.getInnerList()[0].getAs()); - EXPECT_EQ(instances.getInnerList()[0].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[0].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); EXPECT_TRUE(instances.getInnerList()[1].isValid()); EXPECT_TRUE(instances.getInnerList()[1].getAs()); - EXPECT_EQ(instances.getInnerList()[1].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[1].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); EXPECT_TRUE(instances.getInnerList()[2].isValid()); EXPECT_TRUE(instances.getInnerList()[2].getAs()); - EXPECT_EQ(instances.getInnerList()[2].getImplementation().getTypeId(), typeid(TestInheritClass2)); + EXPECT_EQ(instances.getInnerList()[2].tryGetImplementation()->getTypeId(), typeid(TestInheritClass2)); } diff --git a/Tests/Unit/OneOrListTest.cpp b/Tests/Unit/OneOrListTest.cpp index 10a0b69..f5e8183 100644 --- a/Tests/Unit/OneOrListTest.cpp +++ b/Tests/Unit/OneOrListTest.cpp @@ -194,3 +194,29 @@ TEST_F(OneOrListTest, ShouldTryGetAsSingle) EXPECT_FALSE(list.tryGetAsSingle()); } + +TEST_F(OneOrListTest, ShouldForEach) +{ + sb::di::OneOrList list{2}; + list.add(3); + list.add(4); + list.add(5); + + std::vector result; + + list.forEach([&](const int i) { result.push_back(i); }); + + EXPECT_EQ(result, (std::vector{2, 3, 4, 5})); +} + +TEST_F(OneOrListTest, ShouldMap) +{ + sb::di::OneOrList list{2}; + list.add(3); + list.add(4); + list.add(5); + + const std::vector result = list.map([&](const int i) { return i * 2; }); + + EXPECT_EQ(result, (std::vector{4, 6, 8, 10})); +} diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 2571426..2734e45 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -29,7 +29,7 @@ TEST_F(ServiceDescriptorTest, ShouldConstructDescriptor) auto factory = std::make_unique>(); auto act = [&] { sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), std::move(factory)}; + sb::di::ServiceLifeTime::singleton(), std::move(factory), 12}; }; EXPECT_NO_THROW(act()); @@ -39,7 +39,7 @@ TEST_F(ServiceDescriptorTest, ShouldNotFailConstructNullFactoryDescriptor) { auto act = [&] { sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), nullptr}; + sb::di::ServiceLifeTime::singleton(), nullptr, 12}; }; EXPECT_NO_THROW(act()); @@ -50,19 +50,20 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromDescriptor) auto factory = std::make_unique>(); const auto factoryPtr = factory.get(); const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), std::move(factory)}; + sb::di::ServiceLifeTime::singleton(), std::move(factory), 13}; EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); EXPECT_EQ(&descriptor.getImplementationFactory(), factoryPtr); EXPECT_FALSE(descriptor.isAlias()); + EXPECT_EQ(descriptor.getCastOffset(), 13); } TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) { const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), nullptr}; + sb::di::ServiceLifeTime::singleton(), nullptr, 2}; EXPECT_EQ(descriptor.getLifeTime(), sb::di::ServiceLifeTime::singleton()); EXPECT_EQ(descriptor.getServiceTypeId(), typeid(TestClass1)); @@ -70,17 +71,18 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) EXPECT_TRUE(descriptor.isAlias()); auto getFactory = [&] { auto &f = descriptor.getImplementationFactory(); }; EXPECT_THROW((getFactory()), sb::di::NullPointerException); + EXPECT_EQ(descriptor.getCastOffset(), 2); } TEST_F(ServiceDescriptorTest, ShouldCompareDescriptors) { auto factory = std::make_unique>(); const sb::di::ServiceDescriptor descriptor{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), std::move(factory)}; + sb::di::ServiceLifeTime::singleton(), std::move(factory), 2}; auto factory2 = std::make_unique>(); const sb::di::ServiceDescriptor descriptor2{typeid(TestClass1), typeid(TestClass1), - sb::di::ServiceLifeTime::singleton(), std::move(factory2)}; + sb::di::ServiceLifeTime::singleton(), std::move(factory2), 2}; const auto &descriptorCopy = descriptor; EXPECT_EQ(descriptor, descriptorCopy); diff --git a/Tests/Unit/ServiceInstanceTest.cpp b/Tests/Unit/ServiceInstanceTest.cpp new file mode 100644 index 0000000..fff40eb --- /dev/null +++ b/Tests/Unit/ServiceInstanceTest.cpp @@ -0,0 +1,80 @@ +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" + +class ServiceInstanceTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + ServiceInstanceTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~ServiceInstanceTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(ServiceInstanceTest, ShouldCreateEmptyInstance) +{ + sb::di::ServiceInstance instance; + + EXPECT_FALSE(instance); + EXPECT_FALSE(instance.isValid()); + EXPECT_FALSE(instance.tryGetImplementation()); + EXPECT_THROW(instance.getImplementation(), sb::di::NullPointerException); + EXPECT_EQ(instance.getCastOffset(), 0); +} + +TEST_F(ServiceInstanceTest, ShouldCreateInstance) +{ + auto implementation = std::make_unique>(); + sb::di::ServiceInstance instance{std::move(implementation), 12}; + + EXPECT_TRUE(instance); + EXPECT_TRUE(instance.isValid()); + EXPECT_TRUE(instance.tryGetImplementation()); + EXPECT_NO_THROW(instance.getImplementation()); + EXPECT_EQ(instance.getCastOffset(), 12); + EXPECT_TRUE(instance.getAs()); +} + +TEST_F(ServiceInstanceTest, ShouldAddCastOffset) +{ + auto implementation = std::make_unique>(); + sb::di::ServiceInstance instance{std::move(implementation), 12}; + + EXPECT_TRUE(instance); + EXPECT_EQ(instance.getCastOffset(), 12); + instance.addCastOffset(4); + EXPECT_EQ(instance.getCastOffset(), 16); +} + +TEST_F(ServiceInstanceTest, ShouldSetCastOffset) +{ + auto implementation = std::make_unique>(); + sb::di::ServiceInstance instance{std::move(implementation), 12}; + + EXPECT_TRUE(instance); + EXPECT_EQ(instance.getCastOffset(), 12); + instance.setCastOffset(4); + EXPECT_EQ(instance.getCastOffset(), 4); +} + +TEST_F(ServiceInstanceTest, ShouldClear) +{ + auto implementation = std::make_unique>(); + sb::di::ServiceInstance instance{std::move(implementation), 12}; + + EXPECT_TRUE(instance); + instance.clear(); + EXPECT_FALSE(instance); + EXPECT_EQ(instance.getCastOffset(), 0); + EXPECT_FALSE(instance.tryGetImplementation()); +} diff --git a/Tests/Unit/ServiceProviderTest.cpp b/Tests/Unit/ServiceProviderTest.cpp new file mode 100644 index 0000000..8d2927b --- /dev/null +++ b/Tests/Unit/ServiceProviderTest.cpp @@ -0,0 +1,42 @@ +#include + +#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" + +class ServiceProviderTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + ServiceProviderTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~ServiceProviderTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(ServiceProviderTest, ShouldCreateServiceProvider) +{ + sb::di::IServiceInstanceProvider::Ptr instanceProvider = + std::make_unique(); + + auto providerPtr = instanceProvider.get(); + sb::di::ServiceProvider provider{std::move(instanceProvider)}; + + auto &options = provider.getOptions(); + + EXPECT_EQ(options.prebuildSingletons, false); + EXPECT_EQ(options.strongDestructionOrder, false); + EXPECT_EQ(options.checkServiceGlobalUniqueness, true); + EXPECT_EQ(&provider.getInstanceProvider(), providerPtr); +} + +TEST_F(ServiceProviderTest, ShouldFailCreateServiceProvider) +{ + EXPECT_THROW(sb::di::ServiceProvider{nullptr}, sb::di::NullPointerException); +} diff --git a/Tests/Unit/Services/AliasServiceTest.cpp b/Tests/Unit/Services/AliasServiceTest.cpp index 80e8361..627dc17 100644 --- a/Tests/Unit/Services/AliasServiceTest.cpp +++ b/Tests/Unit/Services/AliasServiceTest.cpp @@ -20,7 +20,7 @@ class AliasServiceTest : public testing::Test static void TearDownTestSuite() {} }; -TEST_F(AliasServiceTest, ShouldCreateExternalService) +TEST_F(AliasServiceTest, ShouldCreateAliasService) { TestClass1 test; const sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; @@ -30,7 +30,7 @@ TEST_F(AliasServiceTest, ShouldCreateExternalService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalService) +TEST_F(AliasServiceTest, ShouldFailReleaseAliasService) { TestClass1 test; sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; @@ -39,7 +39,7 @@ TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalService) EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } -TEST_F(AliasServiceTest, ShouldFailMoveOutExternalService) +TEST_F(AliasServiceTest, ShouldFailMoveOutAliasService) { TestClass1 test; sb::di::details::services::AliasService service{&test, typeid(TestClass1)}; @@ -48,16 +48,16 @@ TEST_F(AliasServiceTest, ShouldFailMoveOutExternalService) EXPECT_THROW(service.getForMoveOut(), sb::di::CannotMoveOutServiceException); } -TEST_F(AliasServiceTest, ShouldCreateExternalNullService) +TEST_F(AliasServiceTest, ShouldCreateAliasNullService) { - sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; + const sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; EXPECT_FALSE(service.isValid()); EXPECT_FALSE(service.get()); EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) +TEST_F(AliasServiceTest, ShouldFailReleaseAliasNullService) { sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; @@ -65,7 +65,7 @@ TEST_F(AliasServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) EXPECT_THROW(service.release(), sb::di::CannotReleaseServiceException); } -TEST_F(AliasServiceTest, ShouldFailMoveOutExternalNullService) +TEST_F(AliasServiceTest, ShouldFailMoveOutAliasNullService) { sb::di::details::services::AliasService service{nullptr, typeid(TestClass1)}; diff --git a/Tests/Unit/Services/ExternalServiceTest.cpp b/Tests/Unit/Services/ExternalServiceTest.cpp index 50faa64..a11f154 100644 --- a/Tests/Unit/Services/ExternalServiceTest.cpp +++ b/Tests/Unit/Services/ExternalServiceTest.cpp @@ -30,7 +30,7 @@ TEST_F(ExternalServiceTest, ShouldCreateExternalService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalService) +TEST_F(ExternalServiceTest, ShouldFailReleaseExternalService) { TestClass1 test; sb::di::details::services::ExternalService service{&test}; @@ -50,7 +50,6 @@ TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalService) TEST_F(ExternalServiceTest, ShouldCreateExternalNullService) { - TestClass1 test; const sb::di::details::services::ExternalService service{nullptr}; EXPECT_FALSE(service.isValid()); @@ -58,9 +57,8 @@ TEST_F(ExternalServiceTest, ShouldCreateExternalNullService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) +TEST_F(ExternalServiceTest, ShouldFailReleaseExternalNullService) { - TestClass1 test; sb::di::details::services::ExternalService service{nullptr}; EXPECT_FALSE(service.isValid()); @@ -69,7 +67,6 @@ TEST_F(ExternalServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) TEST_F(ExternalServiceTest, ShouldFailMoveOutExternalNullService) { - TestClass1 test; sb::di::details::services::ExternalService service{nullptr}; EXPECT_FALSE(service.isValid()); diff --git a/Tests/Unit/Services/InPlaceServiceTest.cpp b/Tests/Unit/Services/InPlaceServiceTest.cpp index 4799a3e..edd6742 100644 --- a/Tests/Unit/Services/InPlaceServiceTest.cpp +++ b/Tests/Unit/Services/InPlaceServiceTest.cpp @@ -30,7 +30,7 @@ TEST_F(InPlaceServiceTest, ShouldCreateInPlaceService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(InPlaceServiceTest, ShouldFailMoveAsUniquePtrInPlaceService) +TEST_F(InPlaceServiceTest, ShouldFailReleaseInPlaceService) { TestClass1 test; sb::di::details::services::InPlaceService service{}; diff --git a/Tests/Unit/Services/UniquePtrServiceTest.cpp b/Tests/Unit/Services/UniquePtrServiceTest.cpp index 825c647..815add2 100644 --- a/Tests/Unit/Services/UniquePtrServiceTest.cpp +++ b/Tests/Unit/Services/UniquePtrServiceTest.cpp @@ -30,7 +30,7 @@ TEST_F(UniquePtrServiceTest, ShouldCreateUniquePtrService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(UniquePtrServiceTest, ShouldSuccedMoveAsUniquePtrUniquePtrService) +TEST_F(UniquePtrServiceTest, ShouldSuccedReleasePtrService) { TestClass1 test; sb::di::details::services::UniquePtrService service{std::make_unique()}; @@ -61,13 +61,13 @@ TEST_F(UniquePtrServiceTest, ShouldCreateExternalNullService) EXPECT_EQ(service.getTypeId(), typeid(TestClass1)); } -TEST_F(UniquePtrServiceTest, ShouldFailMoveAsUniquePtrExternalNullService) +TEST_F(UniquePtrServiceTest, ShouldFailReleaseExternalNullService) { TestClass1 test; sb::di::details::services::UniquePtrService service{nullptr}; EXPECT_FALSE(service.isValid()); - EXPECT_FALSE(service.getForMoveOut()); + EXPECT_NO_THROW(service.release()); EXPECT_FALSE(service.isValid()); } @@ -77,6 +77,6 @@ TEST_F(UniquePtrServiceTest, ShouldFailMoveOutExternalNullService) sb::di::details::services::UniquePtrService service{nullptr}; EXPECT_FALSE(service.isValid()); - EXPECT_NO_THROW(service.release()); + EXPECT_FALSE(service.getForMoveOut()); EXPECT_FALSE(service.isValid()); } diff --git a/Tests/Unit/Utils/CastTest.cpp b/Tests/Unit/Utils/CastTest.cpp new file mode 100644 index 0000000..9057bf5 --- /dev/null +++ b/Tests/Unit/Utils/CastTest.cpp @@ -0,0 +1,59 @@ +#include + +#include "SevenBit/DI/Details/Utils/Cast.hpp" + +#include "../../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/Details/Services/ExternalService.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" + +class CastTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + CastTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~CastTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(CastTest, ShouldGetCastOffset) +{ + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_FALSE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); + EXPECT_TRUE((sb::di::details::utils::Cast::getCastOffset())); +} + +TEST_F(CastTest, ShouldApplyCastOffset) +{ + EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(1), 0)), + reinterpret_cast(1)); + EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(1), 1)), + reinterpret_cast(2)); + EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(22), 11)), + reinterpret_cast(33)); + EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(22), -11)), + reinterpret_cast(11)); +} diff --git a/Tests/Unit/Utils/CheckTest.cpp b/Tests/Unit/Utils/CheckTest.cpp index b48f62c..daf61a2 100644 --- a/Tests/Unit/Utils/CheckTest.cpp +++ b/Tests/Unit/Utils/CheckTest.cpp @@ -53,3 +53,20 @@ TEST_F(CheckTest, ShouldCheckEnum) EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::B)); EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::C)); } + +TEST_F(CheckTest, ShoulCheckInstanceValidity) +{ + TestClass1 test; + EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity(nullptr)); + EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity(sb::di::ServiceInstance{})); + EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity( + sb::di::ServiceInstance{std::make_unique>(nullptr)})); + EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity( + sb::di::ServiceInstance{std::make_unique>(&test)})); + EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity( + sb::di::ServiceInstance{std::make_unique>(nullptr)})); + EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity(sb::di::ServiceInstance{ + std::make_unique>(std::make_unique())})); + EXPECT_TRUE(sb::di::details::utils::Check::instanceValidity( + sb::di::ServiceInstance{std::make_unique>()})); +} diff --git a/Tests/Unit/Utils/InheritanceTest.cpp b/Tests/Unit/Utils/InheritanceTest.cpp index 4cfacd6..616403f 100644 --- a/Tests/Unit/Utils/InheritanceTest.cpp +++ b/Tests/Unit/Utils/InheritanceTest.cpp @@ -3,6 +3,7 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "../../Helpers/Classes/Complex.hpp" +#include "../../Helpers/Classes/MultiInherit.hpp" #include "SevenBit/DI/Details/Utils/Inheritance.hpp" class InheritanceTest : public testing::Test @@ -26,6 +27,13 @@ TEST_F(InheritanceTest, ShouldCheckInheritance) EXPECT_TRUE((sb::di::details::utils::InheritanceV)); EXPECT_TRUE((sb::di::details::utils::InheritanceV)); EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); + EXPECT_TRUE((sb::di::details::utils::InheritanceV)); EXPECT_TRUE((sb::di::details::utils::InheritanceV)); EXPECT_TRUE((sb::di::details::utils::InheritanceV)); EXPECT_TRUE((sb::di::details::utils::InheritanceV)); diff --git a/Tests/Unit/Utils/RequireTest.cpp b/Tests/Unit/Utils/RequireTest.cpp index 8eb1581..0ae05af 100644 --- a/Tests/Unit/Utils/RequireTest.cpp +++ b/Tests/Unit/Utils/RequireTest.cpp @@ -67,3 +67,23 @@ TEST_F(RequireTest, ShouldRequireValidEnum) EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::B)); EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::C)); } + +TEST_F(RequireTest, ShoulRequireValidInstance) +{ + TestClass1 test; + EXPECT_THROW(sb::di::details::utils::Require::validInstance(nullptr), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::Require::validInstance(sb::di::ServiceInstance{}), + sb::di::InvalidServiceException); + EXPECT_THROW(sb::di::details::utils::Require::validInstance(sb::di::ServiceInstance{ + std::make_unique>(nullptr)}), + sb::di::InvalidServiceException); + EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance( + sb::di::ServiceInstance{std::make_unique>(&test)})); + EXPECT_THROW(sb::di::details::utils::Require::validInstance(sb::di::ServiceInstance{ + std::make_unique>(nullptr)}), + sb::di::InvalidServiceException); + EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance(sb::di::ServiceInstance{ + std::make_unique>(std::make_unique())})); + EXPECT_NO_THROW(sb::di::details::utils::Require::validInstance( + sb::di::ServiceInstance{std::make_unique>()})); +} From 613844b88f6b42ed94b025ed8a8bb4bc5bca5f75 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Sun, 4 Feb 2024 21:06:43 +0100 Subject: [PATCH 35/45] refactor code --- .../Core/IServiceInstanceProviderRoot.hpp | 21 +++++++++++++++++++ .../Core/Impl/ServiceInstanceProvider.hpp | 7 ++++--- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 6 ++++++ .../Details/Core/ServiceInstanceProvider.hpp | 8 +++---- .../Core/ServiceInstanceProviderRoot.hpp | 10 ++++++--- Tests/Unit/ServiceProviderTest.cpp | 1 - 6 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp diff --git a/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp new file mode 100644 index 0000000..cf3cc53 --- /dev/null +++ b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" +#include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" + +namespace sb::di::details::core +{ + struct IServiceInstanceProviderRoot + { + virtual const containers::ServiceDescriptorsMap &getDescriptorsMap() const = 0; + + virtual containers::ServiceInstancesMap &getSingletons() = 0; + + virtual ServiceInstanceCreator &getRootInstanceCreator() = 0; + + virtual ~IServiceInstanceProviderRoot() = default; + }; +} // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 5c2ed58..4f4cb41 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -3,7 +3,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Exceptions.hpp" @@ -13,7 +12,7 @@ namespace sb::di::details::core { - INLINE ServiceInstanceProvider::ServiceInstanceProvider(ServiceInstanceProviderRoot &root, + INLINE ServiceInstanceProvider::ServiceInstanceProvider(IServiceInstanceProviderRoot &root, const ServiceProviderOptions options) : _options(options), _root(root), _scoped(_options.strongDestructionOrder) { @@ -216,7 +215,9 @@ namespace sb::di::details::core INLINE ServiceInstancesResolver ServiceInstanceProvider::makeResolver(const containers::ServiceDescriptorList &descriptors) { - auto &creator = descriptors.getLifeTime().isSingleton() ? _root._instanceCreator : _instanceCreator; + auto &creator = descriptors.getLifeTime().isSingleton() ? _root.getRootInstanceCreator() : getInstanceCreator(); return ServiceInstancesResolver{creator, descriptors}; } + + INLINE ServiceInstanceCreator &ServiceInstanceProvider::getInstanceCreator() { return _instanceCreator; } } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index 8ea0ea6..4eaa8b6 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -10,6 +10,7 @@ namespace sb::di::details::core : ServiceInstanceProvider(*this, options), _descriptorsMap(options.checkServiceGlobalUniqueness), _singletons(options.strongDestructionOrder) { + _descriptorsMap.seal(); } INLINE void ServiceInstanceProviderRoot::init(ServiceProvider &serviceProvider) @@ -28,6 +29,11 @@ namespace sb::di::details::core INLINE containers::ServiceInstancesMap &ServiceInstanceProviderRoot::getSingletons() { return _singletons; } + INLINE ServiceInstanceCreator &ServiceInstanceProviderRoot::getRootInstanceCreator() + { + return getInstanceCreator(); + } + INLINE void ServiceInstanceProviderRoot::prebuildSingletons() { for (auto &[_, descriptors] : getDescriptorsMap()) diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index ceee548..9ef4bd0 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -7,6 +7,7 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" #include "SevenBit/DI/IServiceInstanceProvider.hpp" @@ -15,19 +16,17 @@ namespace sb::di::details::core { - class ServiceInstanceProviderRoot; - class EXPORT ServiceInstanceProvider : public IServiceInstanceProvider { ServiceProviderOptions _options; ServiceInstanceCreator _instanceCreator; - ServiceInstanceProviderRoot &_root; + IServiceInstanceProviderRoot &_root; containers::ServiceInstancesMap _scoped; public: using Ptr = std::unique_ptr; - ServiceInstanceProvider(ServiceInstanceProviderRoot &root, ServiceProviderOptions options); + ServiceInstanceProvider(IServiceInstanceProviderRoot &root, ServiceProviderOptions options); ServiceInstanceProvider(ServiceInstanceProvider &&) = delete; ServiceInstanceProvider(const ServiceInstanceProvider &) = delete; @@ -73,6 +72,7 @@ namespace sb::di::details::core std::optional> tryCreateAliases(const ServiceDescriptor &descriptor); ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); + ServiceInstanceCreator &getInstanceCreator(); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index ced8f90..4b757bd 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -7,11 +7,13 @@ #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" +#include "SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp" +#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core { - class EXPORT ServiceInstanceProviderRoot : public ServiceInstanceProvider + class EXPORT ServiceInstanceProviderRoot : public ServiceInstanceProvider, public IServiceInstanceProviderRoot { containers::ServiceDescriptorsMap _descriptorsMap; containers::ServiceInstancesMap _singletons; @@ -33,9 +35,11 @@ namespace sb::di::details::core void init(ServiceProvider &serviceProvider) override; - [[nodiscard]] const containers::ServiceDescriptorsMap &getDescriptorsMap() const; + [[nodiscard]] const containers::ServiceDescriptorsMap &getDescriptorsMap() const override; - containers::ServiceInstancesMap &getSingletons(); + containers::ServiceInstancesMap &getSingletons() override; + + ServiceInstanceCreator &getRootInstanceCreator() override; private: void prebuildSingletons(); diff --git a/Tests/Unit/ServiceProviderTest.cpp b/Tests/Unit/ServiceProviderTest.cpp index 8d2927b..2cd8ed5 100644 --- a/Tests/Unit/ServiceProviderTest.cpp +++ b/Tests/Unit/ServiceProviderTest.cpp @@ -1,6 +1,5 @@ #include -#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/ServiceProvider.hpp" From 93001bab8f4362246b3168d617d49fadb48b1fcf Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 5 Feb 2024 17:05:40 +0100 Subject: [PATCH 36/45] refactor and test update --- Benchmarks/Classes.hpp | 2 +- Docs/conf.in.py | 3 +- Docs/conf.py | 3 +- .../Containers/Impl/ServiceDescriptorList.hpp | 2 - .../Containers/Impl/ServiceDescriptorsMap.hpp | 1 + .../Containers/Impl/ServiceInstanceList.hpp | 1 - .../Containers/ServiceDescriptorList.hpp | 2 - .../Containers/ServiceInstanceList.hpp | 2 - .../Containers/ServiceInstancesMap.hpp | 2 +- .../Core/IServiceInstanceProviderRoot.hpp | 2 +- .../Core/Impl/ServiceInstanceCreator.hpp | 7 +- .../Core/Impl/ServiceInstanceProvider.hpp | 88 ++-- .../Core/Impl/ServiceInstanceProviderRoot.hpp | 2 +- .../Core/Impl/ServiceInstancesResolver.hpp | 1 - .../Details/Core/ServiceInstanceCreator.hpp | 4 +- .../Details/Core/ServiceInstanceProvider.hpp | 17 +- .../Core/ServiceInstanceProviderRoot.hpp | 4 - .../Factories/ExternalServiceFactory.hpp | 2 - .../DI/Details/Factories/ServiceFactory.hpp | 1 - .../Details/Factories/ServiceFcnFactory.hpp | 3 +- .../Helpers/ServiceCtorParamConverter.hpp | 4 +- Include/SevenBit/DI/Details/Utils/Assert.hpp | 2 - Include/SevenBit/DI/Details/Utils/Cast.hpp | 7 +- Include/SevenBit/DI/Details/Utils/Check.hpp | 13 +- .../SevenBit/DI/Details/Utils/CheckBase.hpp | 23 + .../DI/Details/Utils/CtorParamsNumber.hpp | 4 +- .../DI/Details/Utils/Impl/Require.hpp | 37 +- .../DI/Details/Utils/RemoveUniquePtr.hpp | 1 - Include/SevenBit/DI/Details/Utils/Require.hpp | 71 +--- .../SevenBit/DI/Details/Utils/RequireBase.hpp | 70 +++ .../SevenBit/DI/Impl/ServiceCollection.hpp | 1 - .../SevenBit/DI/Impl/ServiceDescriptor.hpp | 4 +- Include/SevenBit/DI/Impl/ServiceInstance.hpp | 17 +- Include/SevenBit/DI/Impl/ServiceProvider.hpp | 3 +- Include/SevenBit/DI/OneOrList.hpp | 2 +- Include/SevenBit/DI/ServiceDescriptor.hpp | 2 - Include/SevenBit/DI/ServiceLifeTime.hpp | 6 +- Include/SevenBit/DI/TypeId.hpp | 1 + Tests/Helpers/Classes/CirularDependency.hpp | 10 +- Tests/Helpers/Classes/Dependencies.hpp | 28 +- Tests/Helpers/Classes/InheritDesctuction.hpp | 4 +- Tests/Integration/AliasTest.cpp | 400 ++++++++++++++++++ Tests/Integration/BasicTest.cpp | 269 ++++++++++++ ...ceProviderTest.cpp => InheritanceTest.cpp} | 263 ++---------- ...exInjectionsTest.cpp => InjectionTest.cpp} | 10 +- Tests/Integration/MultiInheritanceTest.cpp | 303 +++++++++++-- ...ceProviderScopesTest.cpp => ScopeTest.cpp} | 27 +- .../Containers/ServiceInstanceListTest.cpp | 8 +- .../Unit/Core/ServiceInstanceCreatorTest.cpp | 32 +- .../Core/ServiceInstanceProviderRootTest.cpp | 2 +- .../Unit/Core/ServiceInstanceResolverTest.cpp | 3 +- .../Factories/ExternalServiceFactoryTest.cpp | 1 - Tests/Unit/Factories/ServiceFactoryTest.cpp | 8 +- .../Unit/Factories/ServiceFcnFactoryTest.cpp | 10 +- Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp | 4 +- .../Helpers/ServiceFactoryInvokerTest.cpp | 4 +- .../Unit/Helpers/ServiceParamProviderTest.cpp | 9 +- Tests/Unit/OneOrListTest.cpp | 58 ++- Tests/Unit/ServiceDescriptorTest.cpp | 2 +- Tests/Unit/ServiceProviderTest.cpp | 4 +- Tests/Unit/Services/InPlaceServiceTest.cpp | 2 - Tests/Unit/Services/UniquePtrServiceTest.cpp | 4 - Tests/Unit/Utils/CheckBaseTest.cpp | 50 +++ Tests/Unit/Utils/CheckTest.cpp | 42 +- Tests/Unit/Utils/CtorParamsNumberTest.cpp | 2 - Tests/Unit/Utils/InheritanceTest.cpp | 2 - Tests/Unit/Utils/IsCopyCtorTest.cpp | 2 - Tests/Unit/Utils/IsInPlaceObjectTest.cpp | 2 - Tests/Unit/Utils/IsUniquePtrTest.cpp | 2 - Tests/Unit/Utils/RemoveUniquePtrTest.cpp | 2 - Tests/Unit/Utils/RequireBaseTest.cpp | 66 +++ Tests/Unit/Utils/RequireTest.cpp | 48 +-- 72 files changed, 1443 insertions(+), 657 deletions(-) create mode 100644 Include/SevenBit/DI/Details/Utils/CheckBase.hpp create mode 100644 Include/SevenBit/DI/Details/Utils/RequireBase.hpp create mode 100644 Tests/Integration/AliasTest.cpp create mode 100644 Tests/Integration/BasicTest.cpp rename Tests/Integration/{ServiceProviderTest.cpp => InheritanceTest.cpp} (51%) rename Tests/Integration/{ComplexInjectionsTest.cpp => InjectionTest.cpp} (90%) rename Tests/Integration/{ServiceProviderScopesTest.cpp => ScopeTest.cpp} (90%) create mode 100644 Tests/Unit/Utils/CheckBaseTest.cpp create mode 100644 Tests/Unit/Utils/RequireBaseTest.cpp diff --git a/Benchmarks/Classes.hpp b/Benchmarks/Classes.hpp index ca872ca..c4885bc 100644 --- a/Benchmarks/Classes.hpp +++ b/Benchmarks/Classes.hpp @@ -144,7 +144,7 @@ struct ITestComplexClass6 virtual ~ITestComplexClass6() = default; }; -class TestComplexClass6 : ITestComplexClass6 +class TestComplexClass6 : public ITestComplexClass6 { std::vector _vec; diff --git a/Docs/conf.in.py b/Docs/conf.in.py index 73b9498..20b9414 100644 --- a/Docs/conf.in.py +++ b/Docs/conf.in.py @@ -1,6 +1,5 @@ -import subprocess import os - +import subprocess currentPath = os.path.dirname(__file__) diff --git a/Docs/conf.py b/Docs/conf.py index 4ac3223..8a3490b 100644 --- a/Docs/conf.py +++ b/Docs/conf.py @@ -1,6 +1,5 @@ -import subprocess import os - +import subprocess currentPath = os.path.dirname(__file__) diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp index 3775828..fd029ce 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorList.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp index 688ad13..9300f23 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceDescriptorsMap.hpp @@ -3,6 +3,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" +#include "SevenBit/DI/Exceptions.hpp" namespace sb::di::details::containers { diff --git a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp index 4d50312..04066ff 100644 --- a/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/Impl/ServiceInstanceList.hpp @@ -4,7 +4,6 @@ #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::containers { diff --git a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp index f82f643..a3d4dc3 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/OneOrList.hpp" diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp index 72e8bc8..c90948c 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstanceList.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/OneOrList.hpp" diff --git a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp index affa07f..61e539e 100644 --- a/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp +++ b/Include/SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp @@ -2,11 +2,11 @@ #include #include +#include #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Containers/ServiceInstanceList.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::containers diff --git a/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp index cf3cc53..a7e3837 100644 --- a/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp @@ -10,7 +10,7 @@ namespace sb::di::details::core { struct IServiceInstanceProviderRoot { - virtual const containers::ServiceDescriptorsMap &getDescriptorsMap() const = 0; + [[nodiscard]] virtual const containers::ServiceDescriptorsMap &getDescriptorsMap() const = 0; virtual containers::ServiceInstancesMap &getSingletons() = 0; diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp index 75263cf..fd9fa49 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceCreator.hpp @@ -7,6 +7,7 @@ #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Details/Services/AliasService.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" namespace sb::di::details::core { @@ -18,7 +19,8 @@ namespace sb::di::details::core INLINE ServiceInstance ServiceInstanceCreator::createInstance(const ServiceDescriptor &descriptor, const bool inPlaceRequest) { - auto &provider = *utils::Require::notNullAndGet(_serviceProvider); + utils::Require::nonAliasDescriptor(descriptor); + auto &provider = *utils::RequireBase::notNullAndGet(_serviceProvider); auto &factory = descriptor.getImplementationFactory(); auto _ = _guard(descriptor.getImplementationTypeId()); @@ -29,6 +31,7 @@ namespace sb::di::details::core INLINE ServiceInstance ServiceInstanceCreator::createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance) { + utils::Require::aliasDescriptor(descriptor); utils::Require::validInstance(instance); auto implementationType = descriptor.getImplementationTypeId(); @@ -36,7 +39,7 @@ namespace sb::di::details::core return createInstance(std::move(implementation), descriptor.getCastOffset()); } - INLINE ServiceInstance ServiceInstanceCreator::createInstance(IServiceInstance::Ptr implementation, + INLINE ServiceInstance ServiceInstanceCreator::createInstance(IServiceInstance::Ptr &&implementation, const ptrdiff_t castOffset) { return utils::Require::validInstanceAndGet(ServiceInstance{std::move(implementation), castOffset}); diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp index 4f4cb41..4b61a0c 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProvider.hpp @@ -5,6 +5,7 @@ #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/Check.hpp" +#include "SevenBit/DI/Details/Utils/Require.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceInstance.hpp" #include "SevenBit/DI/ServiceLifeTimes.hpp" @@ -48,7 +49,7 @@ namespace sb::di::details::core if (!instances) { const auto descriptors = findDescriptors(serviceTypeId, false); - instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreate(*descriptors)) : nullptr; + instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreateNonTransient(*descriptors)) : nullptr; } return instances ? &instances->last() : nullptr; } @@ -59,12 +60,12 @@ namespace sb::di::details::core if (!instances) { const auto descriptors = findDescriptors(serviceTypeId, false); - instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreateAll(*descriptors)) : nullptr; + instances = descriptors ? tryRegisterAndGet(*descriptors, tryCreateAllNonTransient(*descriptors)) : nullptr; } else if (!instances->isSealed()) { const auto descriptors = findDescriptors(serviceTypeId, false); - instances = descriptors ? createRestAndGet(*descriptors, *instances) : nullptr; + instances = descriptors ? createRestNonTransientAndGet(*descriptors, *instances) : nullptr; } return instances ? &instances->getInnerList() : nullptr; } @@ -81,23 +82,15 @@ namespace sb::di::details::core INLINE ServiceInstance ServiceInstanceProvider::tryCreateInstance(const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId, true)) - { - return descriptors->isAlias() ? tryCreateAlias(descriptors->last()) - : makeResolver(*descriptors).createInstance(); - } - return ServiceInstance{}; + const auto descriptors = findDescriptors(serviceTypeId, true); + return descriptors ? tryCreateTransient(*descriptors) : ServiceInstance{}; } INLINE std::optional> ServiceInstanceProvider::tryCreateInstances( const TypeId serviceTypeId) { - if (const auto descriptors = findDescriptors(serviceTypeId, true)) - { - return descriptors->isAlias() ? tryCreateAliases(descriptors->last()) - : std::move(makeResolver(*descriptors).createAllInstances().getInnerList()); - } - return std::nullopt; + const auto descriptors = findDescriptors(serviceTypeId, true); + return descriptors ? tryCreateAllTransient(*descriptors) : std::nullopt; } INLINE ServiceInstance ServiceInstanceProvider::createInstanceInPlace(const TypeId serviceTypeId) @@ -144,66 +137,83 @@ namespace sb::di::details::core } INLINE containers::ServiceInstanceList *ServiceInstanceProvider::tryRegisterAndGet( - const containers::ServiceDescriptorList &descriptors, std::optional instances) + const containers::ServiceDescriptorList &descriptors, + std::optional &&instances) { if (instances) { - auto lifeTime = descriptors.getLifeTime(); - if (descriptors.isAlias()) + auto &descriptor = descriptors.last(); + auto lifeTime = descriptor.getLifeTime(); + if (descriptor.isAlias()) { - const auto originalTypeId = descriptors.last().getImplementationTypeId(); + const auto originalTypeId = descriptor.getImplementationTypeId(); lifeTime = _scoped.contains(originalTypeId) ? ServiceLifeTimes::Scoped : ServiceLifeTimes::Singleton; } auto &instancesMap = lifeTime.isSingleton() ? _root.getSingletons() : _scoped; - return &instancesMap.insert(descriptors.getServiceTypeId(), std::move(*instances)); + return &instancesMap.insert(descriptor.getServiceTypeId(), std::move(*instances)); } return nullptr; } - INLINE std::optional ServiceInstanceProvider::tryCreate( + INLINE std::optional ServiceInstanceProvider::tryCreateNonTransient( const containers::ServiceDescriptorList &descriptors) { - if (descriptors.isAlias()) + if (!descriptors.isAlias()) { - const auto original = tryGetInstance(descriptors.last().getImplementationTypeId()); - return original ? std::make_optional(makeResolver(descriptors).createOneAlias(*original)) : std::nullopt; + utils::Require::nonTransientDescriptors(descriptors); + return makeResolver(descriptors).createOneInstanceInPlace(); } - return makeResolver(descriptors).createOneInstanceInPlace(); + const auto original = tryGetInstance(descriptors.last().getImplementationTypeId()); + return original ? std::make_optional(makeResolver(descriptors).createOneAlias(*original)) : std::nullopt; } - INLINE std::optional ServiceInstanceProvider::tryCreateAll( + INLINE std::optional ServiceInstanceProvider::tryCreateAllNonTransient( const containers::ServiceDescriptorList &descriptors) { - if (descriptors.isAlias()) + if (!descriptors.isAlias()) { - const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); - return originals ? std::make_optional(makeResolver(descriptors).createAllAliases(*originals)) - : std::nullopt; + utils::Require::nonTransientDescriptors(descriptors); + return makeResolver(descriptors).createAllInstancesInPlace(); } - return makeResolver(descriptors).createAllInstancesInPlace(); + const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); + return originals ? std::make_optional(makeResolver(descriptors).createAllAliases(*originals)) : std::nullopt; } - INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRestAndGet( + INLINE containers::ServiceInstanceList *ServiceInstanceProvider::createRestNonTransientAndGet( const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances) { - if (descriptors.isAlias()) + if (!descriptors.isAlias()) { - const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); - return originals ? &makeResolver(descriptors).createRestAliases(*originals, instances) : nullptr; + utils::Require::nonTransientDescriptors(descriptors); + return &makeResolver(descriptors).createRestInstancesInPlace(instances); } - return &makeResolver(descriptors).createRestInstancesInPlace(instances); + const auto originals = tryGetInstances(descriptors.last().getImplementationTypeId()); + return originals ? &makeResolver(descriptors).createRestAliases(*originals, instances) : nullptr; } - INLINE ServiceInstance ServiceInstanceProvider::tryCreateAlias(const ServiceDescriptor &descriptor) + INLINE ServiceInstance + ServiceInstanceProvider::tryCreateTransient(const containers::ServiceDescriptorList &descriptors) { + if (!descriptors.isAlias()) + { + utils::Require::transientDescriptors(descriptors); + return makeResolver(descriptors).createInstance(); + } + auto &descriptor = descriptors.last(); auto alias = tryCreateInstance(descriptor.getImplementationTypeId()); alias.addCastOffset(descriptor.getCastOffset()); return alias; } - INLINE std::optional> ServiceInstanceProvider::tryCreateAliases( - const ServiceDescriptor &descriptor) + INLINE std::optional> ServiceInstanceProvider::tryCreateAllTransient( + const containers::ServiceDescriptorList &descriptors) { + if (!descriptors.isAlias()) + { + utils::Require::transientDescriptors(descriptors); + return std::move(makeResolver(descriptors).createAllInstances().getInnerList()); + } + auto &descriptor = descriptors.last(); auto aliases = tryCreateInstances(descriptor.getImplementationTypeId()); if (aliases && descriptor.getCastOffset()) { diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp index 4eaa8b6..fab7d37 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstanceProviderRoot.hpp @@ -40,7 +40,7 @@ namespace sb::di::details::core { if (!descriptors.isAlias() && descriptors.getLifeTime().isSingleton()) { - tryRegisterAndGet(descriptors, tryCreateAll(descriptors)); + tryRegisterAndGet(descriptors, tryCreateAllNonTransient(descriptors)); } } } diff --git a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp index b163b4f..13b6911 100644 --- a/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp +++ b/Include/SevenBit/DI/Details/Core/Impl/ServiceInstancesResolver.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp index 02ab01b..1196c6b 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp @@ -4,6 +4,8 @@ #include "SevenBit/DI/Details/Helpers/CircularDependencyGuard.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" +#include "SevenBit/DI/ServiceProvider.hpp" namespace sb::di::details::core { @@ -20,7 +22,7 @@ namespace sb::di::details::core ServiceInstance createInstanceAlias(const ServiceDescriptor &descriptor, const ServiceInstance *instance); private: - ServiceInstance createInstance(IServiceInstance::Ptr implementation, ptrdiff_t castOffset); + ServiceInstance createInstance(IServiceInstance::Ptr &&implementation, ptrdiff_t castOffset); }; } // namespace sb::di::details::core diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp index 9ef4bd0..e64e60b 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp @@ -12,7 +12,6 @@ #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" #include "SevenBit/DI/IServiceInstanceProvider.hpp" #include "SevenBit/DI/ServiceProviderOptions.hpp" -#include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::core { @@ -60,16 +59,18 @@ namespace sb::di::details::core bool transient) const; containers::ServiceInstanceList *tryRegisterAndGet(const containers::ServiceDescriptorList &descriptors, - std::optional instances); + std::optional &&instances); - std::optional tryCreate(const containers::ServiceDescriptorList &descriptors); - std::optional tryCreateAll( + std::optional tryCreateNonTransient( const containers::ServiceDescriptorList &descriptors); - containers::ServiceInstanceList *createRestAndGet(const containers::ServiceDescriptorList &descriptors, - containers::ServiceInstanceList &instances); + std::optional tryCreateAllNonTransient( + const containers::ServiceDescriptorList &descriptors); + containers::ServiceInstanceList *createRestNonTransientAndGet( + const containers::ServiceDescriptorList &descriptors, containers::ServiceInstanceList &instances); - ServiceInstance tryCreateAlias(const ServiceDescriptor &descriptor); - std::optional> tryCreateAliases(const ServiceDescriptor &descriptor); + ServiceInstance tryCreateTransient(const containers::ServiceDescriptorList &descriptors); + std::optional> tryCreateAllTransient( + const containers::ServiceDescriptorList &descriptors); ServiceInstancesResolver makeResolver(const containers::ServiceDescriptorList &descriptors); ServiceInstanceCreator &getInstanceCreator(); diff --git a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp index 4b757bd..dff9390 100644 --- a/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp +++ b/Include/SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp @@ -1,15 +1,11 @@ #pragma once #include -#include #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" -#include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" #include "SevenBit/DI/Details/Core/IServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" -#include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di::details::core { diff --git a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp index de7ac92..bb6eaf9 100644 --- a/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp @@ -6,8 +6,6 @@ #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories { diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp index 8fda5aa..9f96121 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFactory.hpp @@ -9,7 +9,6 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" namespace sb::di::details::factories { diff --git a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp index 36349a9..d669523 100644 --- a/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp +++ b/Include/SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp @@ -8,11 +8,10 @@ #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" +#include "SevenBit/DI/Details/Utils/IsInPlaceObject.hpp" #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" #include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" #include "SevenBit/DI/IServiceFactory.hpp" -#include "SevenBit/DI/IServiceInstance.hpp" -#include "SevenBit/DI/TypeId.hpp" namespace sb::di::details::factories { diff --git a/Include/SevenBit/DI/Details/Helpers/ServiceCtorParamConverter.hpp b/Include/SevenBit/DI/Details/Helpers/ServiceCtorParamConverter.hpp index 01d443d..0687c33 100644 --- a/Include/SevenBit/DI/Details/Helpers/ServiceCtorParamConverter.hpp +++ b/Include/SevenBit/DI/Details/Helpers/ServiceCtorParamConverter.hpp @@ -14,11 +14,11 @@ namespace sb::di::details::helpers public: explicit ServiceCtorParamConverter(ServiceProvider &provider, size_t argPos) : _provider(provider) {} - template >> operator U() + template >> operator U() { return helpers::ServiceParamProvider::getParam(_provider); } - template >> operator U &() const + template >> operator U &() const { return helpers::ServiceParamProvider::getParam(_provider); } diff --git a/Include/SevenBit/DI/Details/Utils/Assert.hpp b/Include/SevenBit/DI/Details/Utils/Assert.hpp index bfd7b7e..3dbde98 100644 --- a/Include/SevenBit/DI/Details/Utils/Assert.hpp +++ b/Include/SevenBit/DI/Details/Utils/Assert.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Utils/Inheritance.hpp" diff --git a/Include/SevenBit/DI/Details/Utils/Cast.hpp b/Include/SevenBit/DI/Details/Utils/Cast.hpp index 4e79aab..bf26282 100644 --- a/Include/SevenBit/DI/Details/Utils/Cast.hpp +++ b/Include/SevenBit/DI/Details/Utils/Cast.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include "SevenBit/DI/LibraryConfig.hpp" @@ -9,10 +8,10 @@ namespace sb::di::details::utils { struct Cast { - template static constexpr intptr_t getCastOffset() + template static constexpr intptr_t getCastOffset() { - auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); - auto service = static_cast(implementation); + auto implementation = reinterpret_cast(std::numeric_limits::max() / 2); + auto service = static_cast(implementation); return reinterpret_cast(service) - reinterpret_cast(implementation); }; diff --git a/Include/SevenBit/DI/Details/Utils/Check.hpp b/Include/SevenBit/DI/Details/Utils/Check.hpp index 571b056..479bdbc 100644 --- a/Include/SevenBit/DI/Details/Utils/Check.hpp +++ b/Include/SevenBit/DI/Details/Utils/Check.hpp @@ -1,24 +1,13 @@ #pragma once -#include #include "SevenBit/DI/LibraryConfig.hpp" + #include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { struct EXPORT Check { - template constexpr static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } - - template constexpr static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } - - template constexpr static bool notNull(const T *ptr) { return ptr != nullptr; } - - template constexpr static bool enumValidity(TEnum value) - { - return std::is_enum_v && value >= 0 && value < TEnum::Count; - } - static bool instanceValidity(const ServiceInstance *instance); static bool instanceValidity(const ServiceInstance &instance); diff --git a/Include/SevenBit/DI/Details/Utils/CheckBase.hpp b/Include/SevenBit/DI/Details/Utils/CheckBase.hpp new file mode 100644 index 0000000..eb7d162 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/CheckBase.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +namespace sb::di::details::utils +{ + struct EXPORT CheckBase + { + template constexpr static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } + + template constexpr static bool notNull(const std::shared_ptr &ptr) { return notNull(ptr.get()); } + + template constexpr static bool notNull(const T *ptr) { return ptr != nullptr; } + + template constexpr static bool enumValidity(TEnum value) + { + return std::is_enum_v && value >= 0 && value < TEnum::Count; + } + }; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp b/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp index 0cc90d4..3dd1f4d 100644 --- a/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp +++ b/Include/SevenBit/DI/Details/Utils/CtorParamsNumber.hpp @@ -13,8 +13,8 @@ namespace sb::di::details::utils { explicit Conv(size_t paramNumber) {} - template >> operator U(); - template >> operator U &() const; + template >> operator U(); + template >> operator U &() const; }; template constexpr auto paramsNumber(size_t) -> decltype(T{Conv{Ns}...}, 0) diff --git a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp index 738a4e5..ac6b42d 100644 --- a/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Impl/Require.hpp @@ -3,6 +3,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" namespace sb::di::details::utils { @@ -20,7 +21,7 @@ namespace sb::di::details::utils INLINE void Require::validInstance(const ServiceInstance *instance) { - notNull(instance); + RequireBase::notNull(instance); validInstance(*instance); } @@ -30,9 +31,41 @@ namespace sb::di::details::utils { if (instance.tryGetImplementation()) { - throw InvalidServiceException{instance.tryGetImplementation()->getTypeId()}; + throw InvalidServiceException{instance.getImplementation().getTypeId()}; } throw InvalidServiceException{}; } } + + INLINE void Require::transientDescriptors(const containers::ServiceDescriptorList &descriptors) + { + if (!descriptors.getLifeTime().isTransient()) + { + throw InjectorException{"Expected transient descriptors"}; + } + } + + INLINE void Require::nonTransientDescriptors(const containers::ServiceDescriptorList &descriptors) + { + if (descriptors.getLifeTime().isTransient()) + { + throw InjectorException{"Expected non transient descriptors"}; + } + } + + INLINE void Require::aliasDescriptor(const ServiceDescriptor &descriptor) + { + if (!descriptor.isAlias()) + { + throw InjectorException{"Expected alias descriptor"}; + } + } + + INLINE void Require::nonAliasDescriptor(const ServiceDescriptor &descriptor) + { + if (descriptor.isAlias()) + { + throw InjectorException{"Expected non alias descriptor"}; + } + } } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp b/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp index 2bf6e56..e2eeb5f 100644 --- a/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp +++ b/Include/SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include "SevenBit/DI/LibraryConfig.hpp" diff --git a/Include/SevenBit/DI/Details/Utils/Require.hpp b/Include/SevenBit/DI/Details/Utils/Require.hpp index 0dc37d1..2bce661 100644 --- a/Include/SevenBit/DI/Details/Utils/Require.hpp +++ b/Include/SevenBit/DI/Details/Utils/Require.hpp @@ -1,79 +1,26 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Utils/Check.hpp" -#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" +#include "SevenBit/DI/ServiceDescriptor.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di::details::utils { struct EXPORT Require { - template - static std::unique_ptr &¬NullAndGet(std::unique_ptr &&ptr, std::string_view failMessage = "") - { - notNull(ptr.get(), failMessage); - return std::move(ptr); - } - - template - static std::shared_ptr &¬NullAndGet(std::shared_ptr &&ptr, std::string_view failMessage = "") - { - notNull(ptr.get(), failMessage); - return std::move(ptr); - } - - template static T *notNullAndGet(T *ptr, std::string_view failMessage = "") - { - notNull(ptr, failMessage); - return ptr; - } - - template static void notNull(const std::unique_ptr &ptr, std::string_view failMessage = "") - { - notNull(ptr.get(), failMessage); - } - - template static void notNull(const std::shared_ptr &ptr, std::string_view failMessage = "") - { - notNull(ptr.get(), failMessage); - } - - template static void notNull(const T *ptr, const std::string_view failMessage = "") - { - if (!Check::notNull(ptr)) - { - const auto message = !failMessage.empty() - ? std::string{failMessage} - : std::string{"Object of type: '"} + typeid(T).name() + "' cannot be null"; - throw NullPointerException(message); - } - } - - template constexpr static TEnum validEnumAndGet(TEnum value) - { - validEnum(value); - return value; - } - - template constexpr static void validEnum(TEnum value) - { - if (!Check::enumValidity(value)) - { - throw InjectorException{"enum value: " + std::to_string(value) + " is invalid, shoud be in range [0" + - std::to_string(TEnum::Count) + ")"}; - } - } - static ServiceInstance *validInstanceAndGet(ServiceInstance *instance); - static ServiceInstance &&validInstanceAndGet(ServiceInstance &&instance); static void validInstance(const ServiceInstance *instance); - static void validInstance(const ServiceInstance &instance); + + static void transientDescriptors(const containers::ServiceDescriptorList &descriptors); + static void nonTransientDescriptors(const containers::ServiceDescriptorList &descriptors); + + static void aliasDescriptor(const ServiceDescriptor &descriptor); + static void nonAliasDescriptor(const ServiceDescriptor &descriptor); }; } // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Details/Utils/RequireBase.hpp b/Include/SevenBit/DI/Details/Utils/RequireBase.hpp new file mode 100644 index 0000000..7b37ea9 --- /dev/null +++ b/Include/SevenBit/DI/Details/Utils/RequireBase.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "SevenBit/DI/LibraryConfig.hpp" + +#include "SevenBit/DI/Details/Utils/CheckBase.hpp" +#include "SevenBit/DI/Exceptions.hpp" + +namespace sb::di::details::utils +{ + struct RequireBase + { + template + static std::unique_ptr &¬NullAndGet(std::unique_ptr &&ptr, std::string_view failMessage = "") + { + notNull(ptr.get(), failMessage); + return std::move(ptr); + } + + template + static std::shared_ptr &¬NullAndGet(std::shared_ptr &&ptr, std::string_view failMessage = "") + { + notNull(ptr.get(), failMessage); + return std::move(ptr); + } + + template static T *notNullAndGet(T *ptr, std::string_view failMessage = "") + { + notNull(ptr, failMessage); + return ptr; + } + + template static void notNull(const std::unique_ptr &ptr, std::string_view failMessage = "") + { + notNull(ptr.get(), failMessage); + } + + template static void notNull(const std::shared_ptr &ptr, std::string_view failMessage = "") + { + notNull(ptr.get(), failMessage); + } + + template static void notNull(const T *ptr, const std::string_view failMessage = "") + { + if (!ptr) + { + const auto message = !failMessage.empty() + ? std::string{failMessage} + : std::string{"Object of type: '"} + typeid(T).name() + "' cannot be null"; + throw NullPointerException(message); + } + } + + template constexpr static TEnum validEnumAndGet(TEnum value) + { + validEnum(value); + return value; + } + + template constexpr static void validEnum(TEnum value) + { + if (!CheckBase::enumValidity(value)) + { + throw InjectorException{"enum value: " + std::to_string(value) + " is invalid, shoud be in range [0" + + std::to_string(TEnum::Count) + ")"}; + } + } + }; +} // namespace sb::di::details::utils diff --git a/Include/SevenBit/DI/Impl/ServiceCollection.hpp b/Include/SevenBit/DI/Impl/ServiceCollection.hpp index 000c9d8..61c270a 100644 --- a/Include/SevenBit/DI/Impl/ServiceCollection.hpp +++ b/Include/SevenBit/DI/Impl/ServiceCollection.hpp @@ -4,7 +4,6 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/ServiceCollection.hpp" diff --git a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp index d1315ce..6f6c87c 100644 --- a/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/Impl/ServiceDescriptor.hpp @@ -2,7 +2,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" namespace sb::di @@ -24,7 +24,7 @@ namespace sb::di INLINE const IServiceFactory &ServiceDescriptor::getImplementationFactory() const { - return *details::utils::Require::notNullAndGet(_implementationFactory.get()); + return *details::utils::RequireBase::notNullAndGet(_implementationFactory.get()); } INLINE ptrdiff_t ServiceDescriptor::getCastOffset() const { return _castOffset; } diff --git a/Include/SevenBit/DI/Impl/ServiceInstance.hpp b/Include/SevenBit/DI/Impl/ServiceInstance.hpp index 3a4be9c..be09615 100644 --- a/Include/SevenBit/DI/Impl/ServiceInstance.hpp +++ b/Include/SevenBit/DI/Impl/ServiceInstance.hpp @@ -2,10 +2,9 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" - #include "SevenBit/DI/Details/Utils/Cast.hpp" -#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" +#include "SevenBit/DI/ServiceInstance.hpp" namespace sb::di { @@ -20,20 +19,12 @@ namespace sb::di INLINE IServiceInstance &ServiceInstance::getImplementation() { - if (!_implementation) - { - throw NullPointerException{"service implementation cannot be null"}; - } - return *_implementation; + return *details::utils::RequireBase::notNullAndGet(_implementation.get()); } INLINE const IServiceInstance &ServiceInstance::getImplementation() const { - if (!_implementation) - { - throw NullPointerException{"service implementation cannot be null"}; - } - return *_implementation; + return *details::utils::RequireBase::notNullAndGet(_implementation.get()); } INLINE void ServiceInstance::addCastOffset(const ptrdiff_t castOffset) { _castOffset += castOffset; } diff --git a/Include/SevenBit/DI/Impl/ServiceProvider.hpp b/Include/SevenBit/DI/Impl/ServiceProvider.hpp index 61ddfaa..4ba9e4b 100644 --- a/Include/SevenBit/DI/Impl/ServiceProvider.hpp +++ b/Include/SevenBit/DI/Impl/ServiceProvider.hpp @@ -2,6 +2,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" #include "SevenBit/DI/ServiceProvider.hpp" namespace sb::di @@ -9,7 +10,7 @@ namespace sb::di INLINE ServiceProvider::ServiceProvider(IServiceInstanceProvider::Ptr instanceProvider) : _instanceProvider(std::move(instanceProvider)) { - details::utils::Require::notNull(_instanceProvider); + details::utils::RequireBase::notNull(_instanceProvider); getInstanceProvider().init(*this); } diff --git a/Include/SevenBit/DI/OneOrList.hpp b/Include/SevenBit/DI/OneOrList.hpp index 949ab1c..c9d4ae5 100644 --- a/Include/SevenBit/DI/OneOrList.hpp +++ b/Include/SevenBit/DI/OneOrList.hpp @@ -11,7 +11,7 @@ namespace sb::di { template class OneOrList { - std::variant> _variant; + std::variant> _variant{}; public: explicit OneOrList(const size_t size) : _variant(std::vector{}) { reserve(size); } diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index e666170..b322c8e 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include "SevenBit/DI/LibraryConfig.hpp" #include "SevenBit/DI/IServiceFactory.hpp" diff --git a/Include/SevenBit/DI/ServiceLifeTime.hpp b/Include/SevenBit/DI/ServiceLifeTime.hpp index 9d9e93d..9707774 100644 --- a/Include/SevenBit/DI/ServiceLifeTime.hpp +++ b/Include/SevenBit/DI/ServiceLifeTime.hpp @@ -2,7 +2,7 @@ #include "SevenBit/DI/LibraryConfig.hpp" -#include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" namespace sb::di { @@ -41,7 +41,9 @@ namespace sb::di /** * @brief Construct a new Service Life Time object with specified type */ - constexpr explicit ServiceLifeTime(const Type type) : _type(details::utils::Require::validEnumAndGet(type)) {} + constexpr explicit ServiceLifeTime(const Type type) : _type(details::utils::RequireBase::validEnumAndGet(type)) + { + } constexpr ServiceLifeTime(ServiceLifeTime &&) = default; constexpr ServiceLifeTime(const ServiceLifeTime &) = default; diff --git a/Include/SevenBit/DI/TypeId.hpp b/Include/SevenBit/DI/TypeId.hpp index 39d22db..2005aef 100644 --- a/Include/SevenBit/DI/TypeId.hpp +++ b/Include/SevenBit/DI/TypeId.hpp @@ -12,4 +12,5 @@ namespace sb::di using TypeId = std::type_index; using TypeInfo = std::type_info; + } // namespace sb::di diff --git a/Tests/Helpers/Classes/CirularDependency.hpp b/Tests/Helpers/Classes/CirularDependency.hpp index 42c5e5f..53f35ca 100644 --- a/Tests/Helpers/Classes/CirularDependency.hpp +++ b/Tests/Helpers/Classes/CirularDependency.hpp @@ -5,22 +5,22 @@ struct CircularDependencyB; struct CircularDependencyA { - CircularDependencyA(CircularDependencyB *b) {} + explicit CircularDependencyA(CircularDependencyB *b) {} }; struct CircularDependencyB { - CircularDependencyB(CircularDependencyA *a) {} + explicit CircularDependencyB(CircularDependencyA *a) {} }; struct CircularDependencyUniqueB; struct CircularDependencyUniqueA { - CircularDependencyUniqueA(std::unique_ptr b) {} + explicit CircularDependencyUniqueA(std::unique_ptr b) {} }; struct CircularDependencyUniqueB { - CircularDependencyUniqueB(std::unique_ptr a) {} -}; \ No newline at end of file + explicit CircularDependencyUniqueB(std::unique_ptr a) {} +}; diff --git a/Tests/Helpers/Classes/Dependencies.hpp b/Tests/Helpers/Classes/Dependencies.hpp index 93f440d..8d14641 100644 --- a/Tests/Helpers/Classes/Dependencies.hpp +++ b/Tests/Helpers/Classes/Dependencies.hpp @@ -13,89 +13,91 @@ struct TestDependencyInPlaceClass { TestDependencyClass _test1; - TestDependencyInPlaceClass(TestDependencyClass test1) : _test1(test1) {} + explicit TestDependencyInPlaceClass(TestDependencyClass test1) : _test1(test1) {} }; struct TestDependencyPtrClass1 { TestDependencyClass *_test1; - TestDependencyPtrClass1(TestDependencyClass *test1) : _test1(test1) {} + explicit TestDependencyPtrClass1(TestDependencyClass *test1) : _test1(test1) {} }; struct TestDependencyPtrClass2 { const TestDependencyClass *_test1; - TestDependencyPtrClass2(const TestDependencyClass *test1) : _test1(test1) {} + explicit TestDependencyPtrClass2(const TestDependencyClass *test1) : _test1(test1) {} }; struct TestDependencyPtrClass3 { const TestDependencyClass *const _test1; - TestDependencyPtrClass3(const TestDependencyClass *const test1) : _test1(test1) {} + explicit TestDependencyPtrClass3(const TestDependencyClass *const test1) : _test1(test1) {} }; struct TestDependencyPtrClass4 { TestDependencyClass *const _test1; - TestDependencyPtrClass4(TestDependencyClass *const test1) : _test1(test1) {} + explicit TestDependencyPtrClass4(TestDependencyClass *const test1) : _test1(test1) {} }; struct TestDependencyRefClass1 { TestDependencyClass &_test1; - TestDependencyRefClass1(TestDependencyClass &test1) : _test1(test1) {} + explicit TestDependencyRefClass1(TestDependencyClass &test1) : _test1(test1) {} }; struct TestDependencyRefClass2 { const TestDependencyClass &_test1; - TestDependencyRefClass2(const TestDependencyClass &test1) : _test1(test1) {} + explicit TestDependencyRefClass2(const TestDependencyClass &test1) : _test1(test1) {} }; struct TestDependencyUniquePtrClass1 { std::unique_ptr _test1; - TestDependencyUniquePtrClass1(std::unique_ptr test1) : _test1(std::move(test1)) {} + explicit TestDependencyUniquePtrClass1(std::unique_ptr test1) : _test1(std::move(test1)) {} }; struct TestDependencyUniquePtrClass2 { const std::unique_ptr _test1; - TestDependencyUniquePtrClass2(const std::unique_ptr test1) {} + explicit TestDependencyUniquePtrClass2(const std::unique_ptr test1) {} }; struct TestDependencyVecClass1 { std::vector _test1; - TestDependencyVecClass1(std::vector test1) : _test1(std::move(test1)) {} + explicit TestDependencyVecClass1(std::vector test1) : _test1(std::move(test1)) {} }; struct TestDependencyVecClass2 { const std::vector _test1; - TestDependencyVecClass2(const std::vector test1) : _test1(test1) {} + explicit TestDependencyVecClass2(const std::vector test1) : _test1(test1) {} }; struct TestDependencyVecClass3 { std::vector> _test1; - TestDependencyVecClass3(std::vector> test1) : _test1(std::move(test1)) {} + explicit TestDependencyVecClass3(std::vector> test1) : _test1(std::move(test1)) + { + } }; struct TestDependencyVecClass4 { const std::vector> _test1; - TestDependencyVecClass4(const std::vector> test1) {} + explicit TestDependencyVecClass4(const std::vector> test1) {} }; diff --git a/Tests/Helpers/Classes/InheritDesctuction.hpp b/Tests/Helpers/Classes/InheritDesctuction.hpp index 880cd10..59722e4 100644 --- a/Tests/Helpers/Classes/InheritDesctuction.hpp +++ b/Tests/Helpers/Classes/InheritDesctuction.hpp @@ -16,7 +16,7 @@ struct TestInheritDestrClass4 : TestInheritDestrClass3 template struct TestInheritDestrClass5 final : TestInheritDestrClass4 { Fcn _fcn; - TestInheritDestrClass5(Fcn fcn) : _fcn(fcn) {} + explicit TestInheritDestrClass5(Fcn fcn) : _fcn(fcn) {} - ~TestInheritDestrClass5() { _fcn(); } + ~TestInheritDestrClass5() override { _fcn(); } }; diff --git a/Tests/Integration/AliasTest.cpp b/Tests/Integration/AliasTest.cpp new file mode 100644 index 0000000..c11d43d --- /dev/null +++ b/Tests/Integration/AliasTest.cpp @@ -0,0 +1,400 @@ +#include + +#include "../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class AliasTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + AliasTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~AliasTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(AliasTest, ShouldFailGetServiceDueToAliasMissmatchService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton(); + collection.addSingleton(); + collection.addAlias(); + + EXPECT_THROW(collection.buildServiceProvider(), sb::di::ServiceAliasMismatchException); +} + +TEST_F(AliasTest, ShouldFailGetServiceDueToAliasMissmatchServiceOpposite) +{ + sb::di::ServiceCollection collection; + + collection.addAlias(); + collection.addAlias(); + collection.addSingleton(); + + EXPECT_THROW(collection.buildServiceProvider(), sb::di::ServiceAliasMismatchException); +} + +TEST_F(AliasTest, ShouldTryGetAliasesService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + const auto service1 = provider.tryGetService(); + const auto service2 = provider.tryGetService(); + + EXPECT_TRUE(service1); + EXPECT_TRUE(service2); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_EQ(service1->first(), 2); + EXPECT_EQ(service1->arr[0], 1); + EXPECT_EQ(service1->arr[8], 9); + EXPECT_EQ(service1->end, 1); + EXPECT_EQ(service2->second(), 22); + EXPECT_EQ(service2->arr[0], 1); + EXPECT_EQ(service2->arr[8], 9); + EXPECT_EQ(service2->end, 2); +} + +TEST_F(AliasTest, ShouldNotTryGetAliasesService) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(AliasTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addAlias() + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->first(), 4); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 1); +} + +TEST_F(AliasTest, ShouldTryGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addAlias() + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->first(), 4); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 1); +} + +TEST_F(AliasTest, ShouldGetAliasesService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_EQ(service1.first(), 2); + EXPECT_EQ(service1.arr[0], 1); + EXPECT_EQ(service1.arr[8], 9); + EXPECT_EQ(service1.end, 1); + EXPECT_EQ(service2.second(), 22); + EXPECT_EQ(service2.arr[0], 1); + EXPECT_EQ(service2.arr[8], 9); + EXPECT_EQ(service2.end, 2); +} + +TEST_F(AliasTest, ShouldNotGetAliasesService) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} + +TEST_F(AliasTest, ShouldGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addAlias() + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.first(), 4); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 1); +} + +TEST_F(AliasTest, ShouldGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addAlias() + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.first(), 4); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 1); +} + +TEST_F(AliasTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + auto services = provider.getServices(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); +} + +TEST_F(AliasTest, ShoulNotGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + auto services = provider.getServices(); + + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); +} + +TEST_F(AliasTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addAlias() + .buildServiceProvider(); + + const auto services = provider.getServices(); + + EXPECT_EQ(services.size(), 2); + EXPECT_EQ(services[0]->first(), 3); + EXPECT_EQ(services[1]->first(), 4); +} + +TEST_F(AliasTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addAlias() + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 2); + EXPECT_EQ(services[0]->first(), 3); + EXPECT_EQ(services[1]->first(), 4); +} + +TEST_F(AliasTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + const auto service3 = provider.tryCreateService(); + const auto service4 = provider.tryCreateService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(AliasTest, ShouldNotTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(AliasTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + const auto service3 = provider.createService(); + const auto service4 = provider.createService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(AliasTest, ShouldNotCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(AliasTest, ShouldNotCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(AliasTest, ShouldCreateServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addTransient() + .addAlias() + .addAlias() + .buildServiceProvider(); + + auto services = provider.getServices(); + + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(AliasTest, ShoulNotCreateServices) +{ + auto provider = sb::di::ServiceCollection{} + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .buildServiceProvider(); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(AliasTest, ShouldCreateCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .addAlias() + .buildServiceProvider(); + + const auto services = provider.createServices(); + + EXPECT_EQ(services.size(), 2); + EXPECT_EQ(services[0]->first(), 3); + EXPECT_EQ(services[1]->first(), 4); +} diff --git a/Tests/Integration/BasicTest.cpp b/Tests/Integration/BasicTest.cpp new file mode 100644 index 0000000..0571c27 --- /dev/null +++ b/Tests/Integration/BasicTest.cpp @@ -0,0 +1,269 @@ +#include +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "../Helpers/Classes/CirularDependency.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class BasicTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + BasicTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~BasicTest() override = default; + + static void TearDownTestSuite() {} +}; + +// buildServiceProvider Tests + +TEST_F(BasicTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton(); + collection.addSingleton(); + collection.addSingleton(); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(BasicTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton(); + collection.addSingleton(); + collection.addSingleton(); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +// tryGetService Tests + +TEST_F(BasicTest, ShouldTryGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_TRUE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(BasicTest, ShouldFailTryGetServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .buildServiceProvider(); + + EXPECT_THROW(provider.tryGetService(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldTryGetSelf) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + const auto self = provider.tryGetService(); + EXPECT_TRUE(self); + EXPECT_EQ(self, &provider); +} + +// getService Tests + +TEST_F(BasicTest, ShouldGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_NO_THROW(provider.getService()); + EXPECT_NO_THROW(provider.getService()); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} +TEST_F(BasicTest, ShouldFailGetServiceDueToCircularDependency) +{ + + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .buildServiceProvider(); + + EXPECT_THROW(provider.getService(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldGetSelf) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + auto &self = provider.getService(); + EXPECT_EQ(&self, &provider); +} + +// getServices Tests + +TEST_F(BasicTest, ShouldGetEmptyServicesForNotExisting) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + const auto all = provider.getServices(); + EXPECT_TRUE(all.empty()); +} + +TEST_F(BasicTest, ShouldFailGetServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .buildServiceProvider(); + + EXPECT_THROW(provider.getServices(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldGetSelfServices) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 1); + EXPECT_EQ(services[0], &provider); +} + +// tryCreateService Tests + +TEST_F(BasicTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_TRUE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(BasicTest, ShouldFailTryCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.tryCreateService(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldNotTryCreateSelf) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); +} + +// createService Tests + +TEST_F(BasicTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createService()); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicTest, ShouldFailCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldNotCreateSelfService) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +// createServiceInPlace Tests + +TEST_F(BasicTest, ShouldCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createServiceInPlace()); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicTest, ShouldFailCreateServiceInPlaceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::CircularDependencyException); +} + +// createServices Tests + +TEST_F(BasicTest, ShouldCreateEmptyServicesForNotExisting) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + const auto all = provider.createServices(); + EXPECT_TRUE(all.empty()); +} + +TEST_F(BasicTest, ShouldFaildCreateServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .buildServiceProvider(); + + EXPECT_THROW(provider.createServices(), sb::di::CircularDependencyException); +} + +TEST_F(BasicTest, ShouldFailCreateSelfServices) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + const auto services = provider.createServices(); + EXPECT_TRUE(services.empty()); +} diff --git a/Tests/Integration/ServiceProviderTest.cpp b/Tests/Integration/InheritanceTest.cpp similarity index 51% rename from Tests/Integration/ServiceProviderTest.cpp rename to Tests/Integration/InheritanceTest.cpp index 3db0b95..225b493 100644 --- a/Tests/Integration/ServiceProviderTest.cpp +++ b/Tests/Integration/InheritanceTest.cpp @@ -1,44 +1,27 @@ #include #include -#include "../Helpers/Classes/Basic.hpp" -#include "../Helpers/Classes/CirularDependency.hpp" #include "../Helpers/Classes/Inherit.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceCollection.hpp" -class ServiceProviderTest : public testing::Test +class InheritanceTest : public testing::Test { protected: static void SetUpTestSuite() {} - ServiceProviderTest() {} + InheritanceTest() {} void SetUp() override {} void TearDown() override {} - ~ServiceProviderTest() override = default; + ~InheritanceTest() override = default; static void TearDownTestSuite() {} }; -// buildServiceProvider Tests - -TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredService) -{ - sb::di::ServiceCollection collection; - - collection.addSingleton(); - collection.addSingleton(); - collection.addSingleton(); - - sb::di::ServiceProviderOptions options; - options.checkServiceGlobalUniqueness = true; - EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); -} - -TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredInheritedService) +TEST_F(InheritanceTest, ShouldFailGetServiceDueToAlreadyRegisteredService) { sb::di::ServiceCollection collection; @@ -51,20 +34,7 @@ TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToAlreadyRegisteredInheritedS EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); } -TEST_F(ServiceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) -{ - sb::di::ServiceCollection collection; - - collection.addSingleton(); - collection.addSingleton(); - collection.addSingleton(); - - sb::di::ServiceProviderOptions options; - options.checkServiceGlobalUniqueness = false; - EXPECT_NO_THROW(collection.buildServiceProvider(options)); -} - -TEST_F(ServiceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegisteredInheritedService) +TEST_F(InheritanceTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) { sb::di::ServiceCollection collection; @@ -77,7 +47,7 @@ TEST_F(ServiceProviderTest, ShouldNotFailGetServiceDueToAlreadyRegisteredInherit EXPECT_NO_THROW(collection.buildServiceProvider(options)); } -TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToLifetimeMissmatchInheritedService) +TEST_F(InheritanceTest, ShouldFailGetServiceDueToLifetimeMissmatchService) { sb::di::ServiceCollection collection; @@ -88,23 +58,7 @@ TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToLifetimeMissmatchInheritedS EXPECT_THROW(collection.buildServiceProvider(), sb::di::ServiceLifeTimeMismatchException); } -// tryGetService Tests - -TEST_F(ServiceProviderTest, ShouldTryGetService) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .addTransient() - .buildServiceProvider(); - - EXPECT_TRUE(provider.tryGetService()); - EXPECT_TRUE(provider.tryGetService()); - EXPECT_FALSE(provider.tryGetService()); - EXPECT_FALSE(provider.tryGetService()); -} - -TEST_F(ServiceProviderTest, ShouldTryGetInheritedService) +TEST_F(InheritanceTest, ShouldTryGetService) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -118,7 +72,7 @@ TEST_F(ServiceProviderTest, ShouldTryGetInheritedService) EXPECT_FALSE(provider.tryGetService()); } -TEST_F(ServiceProviderTest, ShouldTryGetOneLastServiceSingleton) +TEST_F(InheritanceTest, ShouldTryGetOneLastServiceSingleton) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -130,7 +84,7 @@ TEST_F(ServiceProviderTest, ShouldTryGetOneLastServiceSingleton) EXPECT_EQ(provider.tryGetService()->number(), 5); } -TEST_F(ServiceProviderTest, ShouldTryGetOneLastServiceScope) +TEST_F(InheritanceTest, ShouldTryGetOneLastServiceScope) { auto provider = sb::di::ServiceCollection{} .addScoped() @@ -142,42 +96,7 @@ TEST_F(ServiceProviderTest, ShouldTryGetOneLastServiceScope) EXPECT_EQ(provider.tryGetService()->number(), 5); } -TEST_F(ServiceProviderTest, ShouldFailTryGetServiceDueToCircularDependency) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .buildServiceProvider(); - - EXPECT_THROW(provider.tryGetService(), sb::di::CircularDependencyException); -} - -TEST_F(ServiceProviderTest, ShouldTryGetSelf) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - const auto self = provider.tryGetService(); - EXPECT_TRUE(self); - EXPECT_EQ(self, &provider); -} - -// getService Tests - -TEST_F(ServiceProviderTest, ShouldGetService) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .addTransient() - .buildServiceProvider(); - - EXPECT_NO_THROW(provider.getService()); - EXPECT_NO_THROW(provider.getService()); - EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); - EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); -} - -TEST_F(ServiceProviderTest, ShouldGetInheritedService) +TEST_F(InheritanceTest, ShouldGetService) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -191,7 +110,7 @@ TEST_F(ServiceProviderTest, ShouldGetInheritedService) EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); } -TEST_F(ServiceProviderTest, ShouldGetOneLastServiceSingleton) +TEST_F(InheritanceTest, ShouldGetOneLastServiceSingleton) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -202,7 +121,7 @@ TEST_F(ServiceProviderTest, ShouldGetOneLastServiceSingleton) EXPECT_EQ(provider.getService().number(), 5); } -TEST_F(ServiceProviderTest, ShouldGetOneLastServiceScope) +TEST_F(InheritanceTest, ShouldGetOneLastServiceScope) { auto provider = sb::di::ServiceCollection{} .addScoped() @@ -213,28 +132,7 @@ TEST_F(ServiceProviderTest, ShouldGetOneLastServiceScope) EXPECT_EQ(provider.getService().number(), 5); } -TEST_F(ServiceProviderTest, ShouldFailGetServiceDueToCircularDependency) -{ - - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .buildServiceProvider(); - - EXPECT_THROW(provider.getService(), sb::di::CircularDependencyException); -} - -TEST_F(ServiceProviderTest, ShouldGetSelf) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - auto &self = provider.getService(); - EXPECT_EQ(&self, &provider); -} - -// getServices Tests - -TEST_F(ServiceProviderTest, ShouldGetInheritedServices) +TEST_F(InheritanceTest, ShouldGetServices) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -248,7 +146,7 @@ TEST_F(ServiceProviderTest, ShouldGetInheritedServices) EXPECT_TRUE(provider.getServices().empty()); } -TEST_F(ServiceProviderTest, ShouldGetCastedServicesInOrder) +TEST_F(InheritanceTest, ShouldGetCastedServicesInOrder) { auto provider = sb::di::ServiceCollection{} .addScoped() @@ -267,7 +165,7 @@ TEST_F(ServiceProviderTest, ShouldGetCastedServicesInOrder) EXPECT_EQ(services[4]->number(), 5); } -TEST_F(ServiceProviderTest, ShouldGetServicesInOrderAfterNormalGet) +TEST_F(InheritanceTest, ShouldGetServicesInOrderAfterNormalGet) { auto provider = sb::di::ServiceCollection{} .addScoped() @@ -288,50 +186,7 @@ TEST_F(ServiceProviderTest, ShouldGetServicesInOrderAfterNormalGet) EXPECT_TRUE(provider.tryGetService()); } -TEST_F(ServiceProviderTest, ShouldGetEmptyServicesForNotExisting) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - const auto all = provider.getServices(); - EXPECT_TRUE(all.empty()); -} - -TEST_F(ServiceProviderTest, ShouldFailGetServicesDueToCircularDependency) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .buildServiceProvider(); - - EXPECT_THROW(provider.getServices(), sb::di::CircularDependencyException); -} - -TEST_F(ServiceProviderTest, ShouldGetSelfServices) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - const auto services = provider.getServices(); - EXPECT_EQ(services.size(), 1); - EXPECT_EQ(services[0], &provider); -} - -// tryCreateService Tests - -TEST_F(ServiceProviderTest, ShouldTryCreateService) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .addTransient() - .buildServiceProvider(); - - EXPECT_FALSE(provider.tryCreateService()); - EXPECT_FALSE(provider.tryCreateService()); - EXPECT_TRUE(provider.tryCreateService()); - EXPECT_FALSE(provider.tryCreateService()); -} - -TEST_F(ServiceProviderTest, ShouldTryCreateInheritedService) +TEST_F(InheritanceTest, ShouldTryCreateService) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -345,40 +200,7 @@ TEST_F(ServiceProviderTest, ShouldTryCreateInheritedService) EXPECT_FALSE(provider.tryCreateService()); } -TEST_F(ServiceProviderTest, ShouldFailTryCreateServiceDueToCircularDependency) -{ - auto provider = sb::di::ServiceCollection{} - .addTransient() - .addTransient() - .buildServiceProvider(); - - EXPECT_THROW(provider.tryCreateService(), sb::di::CircularDependencyException); -} - -TEST_F(ServiceProviderTest, ShouldNotTryCreateSelf) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - EXPECT_FALSE(provider.tryCreateService()); -} - -// createService Tests - -TEST_F(ServiceProviderTest, ShouldCreateService) -{ - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addScoped() - .addTransient() - .buildServiceProvider(); - - EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); - EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); - EXPECT_NO_THROW(provider.createService()); - EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); -} - -TEST_F(ServiceProviderTest, ShouldCreateInheritedService) +TEST_F(InheritanceTest, ShouldCreateService) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -392,26 +214,21 @@ TEST_F(ServiceProviderTest, ShouldCreateInheritedService) EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); } -TEST_F(ServiceProviderTest, ShouldFailCreateServiceDueToCircularDependency) +TEST_F(InheritanceTest, ShouldCreateServiceInPlace) { auto provider = sb::di::ServiceCollection{} - .addTransient() - .addTransient() + .addSingleton() + .addScoped() + .addTransient() .buildServiceProvider(); - EXPECT_THROW(provider.createService(), sb::di::CircularDependencyException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); } -TEST_F(ServiceProviderTest, ShouldNotCreateSelfService) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); -} - -// createServices Tests - -TEST_F(ServiceProviderTest, ShouldCreateInheritedServices) +TEST_F(InheritanceTest, ShouldCreateServices) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -425,7 +242,7 @@ TEST_F(ServiceProviderTest, ShouldCreateInheritedServices) EXPECT_TRUE(provider.createServices().empty()); } -TEST_F(ServiceProviderTest, ShouldCreateServicesInOrder) +TEST_F(InheritanceTest, ShouldCreateServicesInOrder) { auto provider = sb::di::ServiceCollection{} .addTransient() @@ -443,29 +260,3 @@ TEST_F(ServiceProviderTest, ShouldCreateServicesInOrder) EXPECT_EQ(services[3]->number(), 4); EXPECT_EQ(services[4]->number(), 5); } - -TEST_F(ServiceProviderTest, ShouldCreateEmptyServicesForNotExisting) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - const auto all = provider.createServices(); - EXPECT_TRUE(all.empty()); -} - -TEST_F(ServiceProviderTest, ShouldFaildCreateServicesDueToCircularDependency) -{ - auto provider = sb::di::ServiceCollection{} - .addTransient() - .addTransient() - .buildServiceProvider(); - - EXPECT_THROW(provider.createServices(), sb::di::CircularDependencyException); -} - -TEST_F(ServiceProviderTest, ShouldFailCreateSelfServices) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - const auto services = provider.createServices(); - EXPECT_TRUE(services.empty()); -} diff --git a/Tests/Integration/ComplexInjectionsTest.cpp b/Tests/Integration/InjectionTest.cpp similarity index 90% rename from Tests/Integration/ComplexInjectionsTest.cpp rename to Tests/Integration/InjectionTest.cpp index c67d2c8..7fe0228 100644 --- a/Tests/Integration/ComplexInjectionsTest.cpp +++ b/Tests/Integration/InjectionTest.cpp @@ -4,25 +4,25 @@ #include "../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/ServiceCollection.hpp" -class ComplexInjectionsTest : public testing::Test +class InjectionTest : public testing::Test { protected: static void SetUpTestSuite() {} - ComplexInjectionsTest() {} + InjectionTest() {} void SetUp() override {} void TearDown() override {} - ~ComplexInjectionsTest() override = default; + ~InjectionTest() override = default; static void TearDownTestSuite() {} }; // buildServiceProvider Tests -TEST_F(ComplexInjectionsTest, ShouldGetService) +TEST_F(InjectionTest, ShouldGetService) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -61,7 +61,7 @@ TEST_F(ComplexInjectionsTest, ShouldGetService) EXPECT_NE(service6.makeThree(), service3); } -TEST_F(ComplexInjectionsTest, ShouldTryGetDeepNestedService) +TEST_F(InjectionTest, ShouldTryGetDeepNestedService) { sb::di::ServiceCollection collection; diff --git a/Tests/Integration/MultiInheritanceTest.cpp b/Tests/Integration/MultiInheritanceTest.cpp index 3083829..fa50bb7 100644 --- a/Tests/Integration/MultiInheritanceTest.cpp +++ b/Tests/Integration/MultiInheritanceTest.cpp @@ -20,6 +20,83 @@ class MultiInheritanceTest : public testing::Test static void TearDownTestSuite() {} }; +TEST_F(MultiInheritanceTest, ShouldTryGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + auto service1 = provider.tryGetService(); + auto service2 = provider.tryGetService(); + auto service5 = provider.tryGetService(); + auto service6 = provider.tryGetService(); + + EXPECT_TRUE(service1); + EXPECT_TRUE(service2); + EXPECT_TRUE(service5); + EXPECT_TRUE(service6); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_EQ(service1->first(), 2); + EXPECT_EQ(service1->arr[0], 1); + EXPECT_EQ(service1->arr[8], 9); + EXPECT_EQ(service1->end, 1); + EXPECT_EQ(service2->second(), 22); + EXPECT_EQ(service2->arr[0], 1); + EXPECT_EQ(service2->arr[8], 9); + EXPECT_EQ(service2->end, 2); + EXPECT_EQ(service5->second(), 44); + EXPECT_EQ(service5->third(), 444); + EXPECT_EQ(service5->arr[0], 1); + EXPECT_EQ(service5->arr[8], 9); + EXPECT_EQ(service5->end, 5); + EXPECT_EQ(service6->fourth(), 4444); + EXPECT_EQ(service6->arr[0], 1); + EXPECT_EQ(service6->arr[8], 9); + EXPECT_EQ(service6->end, 6); +} + +TEST_F(MultiInheritanceTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addSingleton() + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + +TEST_F(MultiInheritanceTest, ShouldTryGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addScoped() + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + TEST_F(MultiInheritanceTest, ShouldGetService) { sb::di::ServiceProviderOptions options; @@ -35,11 +112,11 @@ TEST_F(MultiInheritanceTest, ShouldGetService) auto &service1 = provider.getService(); auto &service2 = provider.getService(); - auto service3 = provider.createService(); - auto service4 = provider.createService(); auto &service5 = provider.getService(); auto &service6 = provider.getService(); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); EXPECT_EQ(service1.first(), 2); EXPECT_EQ(service1.arr[0], 1); EXPECT_EQ(service1.arr[8], 9); @@ -48,15 +125,6 @@ TEST_F(MultiInheritanceTest, ShouldGetService) EXPECT_EQ(service2.arr[0], 1); EXPECT_EQ(service2.arr[8], 9); EXPECT_EQ(service2.end, 2); - EXPECT_EQ(service3->first(), 3); - EXPECT_EQ(service3->second(), 33); - EXPECT_EQ(service3->arr[0], 1); - EXPECT_EQ(service3->arr[8], 9); - EXPECT_EQ(service3->end, 3); - EXPECT_EQ(service4->third(), 333); - EXPECT_EQ(service4->arr[0], 1); - EXPECT_EQ(service4->arr[8], 9); - EXPECT_EQ(service4->end, 4); EXPECT_EQ(service5.first(), 4); EXPECT_EQ(service5.second(), 44); EXPECT_EQ(service5.third(), 444); @@ -69,38 +137,193 @@ TEST_F(MultiInheritanceTest, ShouldGetService) EXPECT_EQ(service6.end, 6); } -TEST_F(MultiInheritanceTest, ShouldGetAliasesService) +TEST_F(MultiInheritanceTest, ShouldGetOneLastServiceSingleton) { auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addAlias() - .addAlias() - .addTransient() - .addAlias() - .addAlias() + .addSingleton() + .addSingleton() + .addSingleton() .buildServiceProvider(); - auto &service1 = provider.getService(); - auto &service2 = provider.getService(); - auto service3 = provider.createService(); - auto service4 = provider.createService(); + auto &service = provider.getService(); - EXPECT_EQ(service1.first(), 2); - EXPECT_EQ(service1.arr[0], 1); - EXPECT_EQ(service1.arr[8], 9); - EXPECT_EQ(service1.end, 1); - EXPECT_EQ(service2.second(), 22); - EXPECT_EQ(service2.arr[0], 1); - EXPECT_EQ(service2.arr[8], 9); - EXPECT_EQ(service2.end, 2); - EXPECT_EQ(service3->first(), 4); - EXPECT_EQ(service3->second(), 44); - EXPECT_EQ(service3->third(), 444); - EXPECT_EQ(service3->arr[0], 1); - EXPECT_EQ(service3->arr[8], 9); - EXPECT_EQ(service3->end, 5); - EXPECT_EQ(service4->fourth(), 4444); - EXPECT_EQ(service4->arr[0], 1); - EXPECT_EQ(service4->arr[8], 9); - EXPECT_EQ(service4->end, 6); + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceTest, ShouldGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addScoped() + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceTest, ShouldGetServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); +} + +TEST_F(MultiInheritanceTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addScoped() + .buildServiceProvider(); + + const auto services = provider.getServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped() + .addScoped() + .addScoped() + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceTest, ShouldTryCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + const auto service3 = provider.tryCreateService(); + const auto service4 = provider.tryCreateService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(MultiInheritanceTest, ShouldCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + auto service3 = provider.createService(); + auto service4 = provider.createService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceTest, ShouldNotCreateServiceInPlace) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceTest, ShouldCreateServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addTransient() + .addTransient() + .addScoped() + .addScoped() + .buildServiceProvider(options); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(MultiInheritanceTest, ShouldCreateServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient() + .addTransient() + .addTransient() + .buildServiceProvider(); + + const auto services = provider.createServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); } diff --git a/Tests/Integration/ServiceProviderScopesTest.cpp b/Tests/Integration/ScopeTest.cpp similarity index 90% rename from Tests/Integration/ServiceProviderScopesTest.cpp rename to Tests/Integration/ScopeTest.cpp index 5fcf2a8..a8f1d91 100644 --- a/Tests/Integration/ServiceProviderScopesTest.cpp +++ b/Tests/Integration/ScopeTest.cpp @@ -4,40 +4,39 @@ #include "../Helpers/Classes/Basic.hpp" #include "../Helpers/Classes/Complex.hpp" #include "../Helpers/Classes/Dependencies.hpp" -#include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceCollection.hpp" #include "SevenBit/DI/ServiceProvider.hpp" -class ServiceProviderScopesTest : public testing::Test +class ScopeTest : public testing::Test { protected: static void SetUpTestSuite() {} - ServiceProviderScopesTest() {} + ScopeTest() {} void SetUp() override {} void TearDown() override {} - ~ServiceProviderScopesTest() override = default; + ~ScopeTest() override = default; static void TearDownTestSuite() {} }; -TEST_F(ServiceProviderScopesTest, ShouldMakeScopedProvider) +TEST_F(ScopeTest, ShouldMakeScopedProvider) { - auto provider = sb::di::ServiceCollection{} - .addSingleton() - .addSingleton() - .addSingleton() - .buildServiceProvider(); + const auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addSingleton() + .addSingleton() + .buildServiceProvider(); auto act = [&] { auto scoped = provider.createScope(); }; EXPECT_NO_THROW(act()); } -TEST_F(ServiceProviderScopesTest, ShouldGetProperServicesRefWithScopedProvider) +TEST_F(ScopeTest, ShouldGetProperServicesRefWithScopedProvider) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -83,7 +82,7 @@ TEST_F(ServiceProviderScopesTest, ShouldGetProperServicesRefWithScopedProvider) EXPECT_NE(provider.createService(), provider.createService()); } -TEST_F(ServiceProviderScopesTest, ShouldReturnProperSelfForScope) +TEST_F(ScopeTest, ShouldReturnProperSelfForScope) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -100,7 +99,7 @@ TEST_F(ServiceProviderScopesTest, ShouldReturnProperSelfForScope) EXPECT_EQ(scoped3.tryGetService(), &scoped3); } -TEST_F(ServiceProviderScopesTest, ShouldGetServicesDeeperRefWithScopedProvider) +TEST_F(ScopeTest, ShouldGetServicesDeeperRefWithScopedProvider) { auto provider = sb::di::ServiceCollection{} .addSingleton() @@ -127,7 +126,7 @@ TEST_F(ServiceProviderScopesTest, ShouldGetServicesDeeperRefWithScopedProvider) EXPECT_EQ(&transientFromTop->_test1, &transientFromScoped->_test1); } -TEST_F(ServiceProviderScopesTest, ShouldGetComplexServices) +TEST_F(ScopeTest, ShouldGetComplexServices) { auto provider = sb::di::ServiceCollection{} .addSingleton() diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index f4f2897..b9ce038 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -37,19 +37,19 @@ TEST_F(ServiceInstanceListTest, ShouldAddServices) TEST_F(ServiceInstanceListTest, ShouldFailAddNullService) { - auto act = [&]() { sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{}}; }; + auto act = [&] { sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{}}; }; - EXPECT_THROW((act()), sb::di::InvalidServiceException); + EXPECT_THROW(act(), sb::di::InvalidServiceException); } TEST_F(ServiceInstanceListTest, ShouldFailAddInvalidService) { - auto act = [&]() { + auto act = [&] { auto implementation = std::make_unique>(nullptr); sb::di::details::containers::ServiceInstanceList list{sb::di::ServiceInstance{std::move(implementation)}}; }; - EXPECT_THROW((act()), sb::di::InvalidServiceException); + EXPECT_THROW(act(), sb::di::InvalidServiceException); } TEST_F(ServiceInstanceListTest, ShouldReturnProperSize) diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp index 63bccdd..3e1ff8b 100644 --- a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -45,7 +45,7 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) { sb::di::details::core::ServiceInstanceCreator creator; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const auto descriptor = sb::di::ServiceDescriber::describeAlias(); TestInheritClass5 test; const sb::di::ServiceInstance external{ @@ -54,7 +54,7 @@ TEST_F(ServiceInstanceCreatorTest, ShouldCreateInstanceAlias) EXPECT_TRUE(instance.isValid()); EXPECT_TRUE(instance.getAs()); - EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass3)); + EXPECT_EQ(instance.tryGetImplementation()->getTypeId(), typeid(TestInheritClass5)); } TEST_F(ServiceInstanceCreatorTest, ShouldFailForNullProvider) @@ -78,6 +78,17 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailForInvalidInstance) EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::InvalidServiceException); } +TEST_F(ServiceInstanceCreatorTest, ShouldFailFoWringDescriptor) +{ + ServiceProviderMock mock; + sb::di::details::core::ServiceInstanceCreator creator; + creator.setServiceProvider(mock); + + const auto descriptor = sb::di::ServiceDescriber::describeAlias(); + + EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::InjectorException); +} + TEST_F(ServiceInstanceCreatorTest, ShouldFailForCirculatDependency) { ServiceProviderMock mock; @@ -103,11 +114,11 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailForCirculatDependency) EXPECT_THROW(creator.createInstance(descriptor, false), sb::di::CircularDependencyException); } -TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) +TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAliasForNullService) { sb::di::details::core::ServiceInstanceCreator creator; - const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + const auto descriptor = sb::di::ServiceDescriber::describeAlias(); TestInheritClass5 *test = nullptr; const sb::di::ServiceInstance external{ @@ -115,3 +126,16 @@ TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAlias) EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InvalidServiceException); } + +TEST_F(ServiceInstanceCreatorTest, ShouldFailCreateInstanceAliasForWrongDescriptor) +{ + sb::di::details::core::ServiceInstanceCreator creator; + + const auto descriptor = sb::di::ServiceDescriber::describeSingleton(); + + TestInheritClass5 *test = nullptr; + const sb::di::ServiceInstance external{ + std::make_unique>(test)}; + + EXPECT_THROW(creator.createInstanceAlias(descriptor, &external), sb::di::InjectorException); +} diff --git a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp index dc8c772..9b9fc9a 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp @@ -35,7 +35,7 @@ TEST_F(ServiceInstanceProviderRootTest, ShouldGetOptions) sb::di::details::core::ServiceInstanceProviderRoot provider(describers.begin(), describers.end()); provider.init(mock); - const auto options = provider.getOptions(); + const auto &options = provider.getOptions(); EXPECT_FALSE(options.prebuildSingletons); EXPECT_FALSE(options.strongDestructionOrder); EXPECT_TRUE(options.checkServiceGlobalUniqueness); diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp index 5bcc836..304a15c 100644 --- a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -6,7 +6,6 @@ #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" -#include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceCollection.hpp" class ServiceInstanceResolverTest : public testing::Test @@ -344,7 +343,7 @@ TEST_F(ServiceInstanceResolverTest, ShouldCreateAlias) const sb::di::details::core::ServiceInstancesResolver resolver{creator, descriptors}; TestInheritClass6 test; - sb::di::ServiceInstance external{ + const sb::di::ServiceInstance external{ std::make_unique>(&test)}; const auto instance = resolver.createAlias(external); diff --git a/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp b/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp index 5b55cc2..57f4293 100644 --- a/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ExternalServiceFactoryTest.cpp @@ -3,7 +3,6 @@ #include "../../Helpers/Classes/Basic.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Factories/ExternalServiceFactory.hpp" -#include "SevenBit/DI/Exceptions.hpp" class ExternalServiceFactoryTest : public testing::Test { diff --git a/Tests/Unit/Factories/ServiceFactoryTest.cpp b/Tests/Unit/Factories/ServiceFactoryTest.cpp index 87951f3..7d4adae 100644 --- a/Tests/Unit/Factories/ServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFactoryTest.cpp @@ -222,7 +222,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec1Service) ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -242,7 +242,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec2Service) ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -263,7 +263,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec3Service) auto service = std::make_unique(); sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -285,7 +285,7 @@ TEST_F(ServiceFactoryTest, ShouldCreateDependencyVec4Service) sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index 972f5b4..9c2b4e2 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -71,7 +71,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyInPlaceService) .WillOnce(testing::Return(std::move(test1))); const sb::di::details::factories::ServiceFcnFactory factory{ - [&](TestDependencyClass ob) { return TestDependencyInPlaceClass(ob); }}; + [&](const TestDependencyClass ob) { return TestDependencyInPlaceClass(ob); }}; const auto instance = factory.createInstance(mock, true); @@ -245,7 +245,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec1Service) ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -265,7 +265,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec2Service) { ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -288,7 +288,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec3Service) auto service = std::make_unique(); sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -311,7 +311,7 @@ TEST_F(ServiceFcnFactoryTest, ShouldCreateDependencyVec4Service) sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp index 792772b..8bf10d8 100644 --- a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp @@ -32,8 +32,8 @@ TEST_F(ServiceCtorInvokerTest, ShouldInvokeFuncWithCtorParams) sb::di::details::helpers::ServiceCtorInvoker invoker{mock}; - auto func = [&](TestDependencyClass *test1) { - EXPECT_TRUE(test1); + auto func = [&](TestDependencyClass *service) { + EXPECT_TRUE(service); return 1; }; EXPECT_EQ(invoker.invokeWithCtorParams(func), 1); diff --git a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp index 514c919..c7e3088 100644 --- a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp @@ -30,8 +30,8 @@ TEST_F(ServiceFactoryInvokerTest, ShouldInvokeFuncFactory) EXPECT_CALL(mock.getMock(), tryGetInstance(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&test1)); - auto func = [&](TestDependencyClass *test1) { - EXPECT_TRUE(test1); + auto func = [&](TestDependencyClass *service) { + EXPECT_TRUE(service); return 1; }; diff --git a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp index c98a951..b8ca5f6 100644 --- a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp +++ b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp @@ -3,7 +3,6 @@ #include "../../Helpers/Classes/Dependencies.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Helpers/ServiceParamProvider.hpp" -#include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/ServiceProvider.hpp" @@ -177,7 +176,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec1Service) ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -194,7 +193,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec2Service) { ServiceProviderMock mock; sb::di::ServiceInstance test1{std::make_unique>()}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryGetInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(&result)); @@ -213,7 +212,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec3Service) auto service = std::make_unique(); sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); @@ -234,7 +233,7 @@ TEST_F(ServiceParamProviderTest, ShouldGetDependencyVec4Service) sb::di::ServiceInstance test1{ std::make_unique>(std::move(service))}; - sb::di::OneOrList result{std::move(test1)}; + sb::di::OneOrList result{std::move(test1)}; EXPECT_CALL(mock.getMock(), tryCreateInstances(sb::di::TypeId{typeid(TestDependencyClass)})) .WillOnce(testing::Return(std::make_optional(std::move(result)))); diff --git a/Tests/Unit/OneOrListTest.cpp b/Tests/Unit/OneOrListTest.cpp index f5e8183..619cbd3 100644 --- a/Tests/Unit/OneOrListTest.cpp +++ b/Tests/Unit/OneOrListTest.cpp @@ -20,7 +20,7 @@ class OneOrListTest : public testing::Test TEST_F(OneOrListTest, ShouldCreateSingle) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_FALSE(list.isList()); EXPECT_EQ(list.first(), 2); @@ -28,7 +28,7 @@ TEST_F(OneOrListTest, ShouldCreateSingle) TEST_F(OneOrListTest, ShouldCreateList) { - sb::di::OneOrList list(2); + sb::di::OneOrList list(2); list.reserve(2); EXPECT_TRUE(list.isList()); @@ -37,7 +37,7 @@ TEST_F(OneOrListTest, ShouldCreateList) TEST_F(OneOrListTest, ShouldMove) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; auto newList = std::move(list); @@ -49,7 +49,7 @@ TEST_F(OneOrListTest, ShouldMove) TEST_F(OneOrListTest, ShouldAdd) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; list.add(3); list.add(4); @@ -62,7 +62,7 @@ TEST_F(OneOrListTest, ShouldAdd) TEST_F(OneOrListTest, ShouldGetFirst) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_EQ(list.first(), 2); @@ -75,7 +75,7 @@ TEST_F(OneOrListTest, ShouldGetFirst) TEST_F(OneOrListTest, ShouldGetLast) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_EQ(list.last(), 2); @@ -88,7 +88,9 @@ TEST_F(OneOrListTest, ShouldGetLast) TEST_F(OneOrListTest, ShouldGetIndexed) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; + + EXPECT_EQ(list[0], 2); list.add(3); list.add(4); @@ -102,7 +104,7 @@ TEST_F(OneOrListTest, ShouldGetIndexed) TEST_F(OneOrListTest, ShouldGetSize) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_EQ(list.size(), 1); @@ -117,7 +119,7 @@ TEST_F(OneOrListTest, ShouldGetSize) TEST_F(OneOrListTest, ShouldGetEmpty) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_FALSE(list.empty()); @@ -132,7 +134,7 @@ TEST_F(OneOrListTest, ShouldGetEmpty) TEST_F(OneOrListTest, ShouldGetIsList) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_FALSE(list.isList()); @@ -145,7 +147,7 @@ TEST_F(OneOrListTest, ShouldGetIsList) TEST_F(OneOrListTest, ShouldGetAsList) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_THROW(list.getAsList(), std::bad_variant_access); @@ -153,12 +155,12 @@ TEST_F(OneOrListTest, ShouldGetAsList) list.add(4); list.add(5); - EXPECT_EQ(list.getAsList(), (std::vector{2, 3, 4, 5})); + EXPECT_EQ(list.getAsList(), (std::vector{2, 3, 4, 5})); } TEST_F(OneOrListTest, ShouldGetAsSingle) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_EQ(list.getAsSingle(), 2); @@ -171,7 +173,7 @@ TEST_F(OneOrListTest, ShouldGetAsSingle) TEST_F(OneOrListTest, ShouldGetTryGetAsList) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_FALSE(list.tryGetAsList()); @@ -179,12 +181,12 @@ TEST_F(OneOrListTest, ShouldGetTryGetAsList) list.add(4); list.add(5); - EXPECT_EQ(*list.tryGetAsList(), (std::vector{2, 3, 4, 5})); + EXPECT_EQ(*list.tryGetAsList(), (std::vector{2, 3, 4, 5})); } TEST_F(OneOrListTest, ShouldTryGetAsSingle) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; EXPECT_EQ(*list.tryGetAsSingle(), 2); @@ -197,26 +199,36 @@ TEST_F(OneOrListTest, ShouldTryGetAsSingle) TEST_F(OneOrListTest, ShouldForEach) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; + std::vector result; + + list.forEach([&](const int i) { result.push_back(i); }); + + EXPECT_EQ(result, std::vector{2}); + result.clear(); + list.add(3); list.add(4); list.add(5); - std::vector result; - list.forEach([&](const int i) { result.push_back(i); }); - EXPECT_EQ(result, (std::vector{2, 3, 4, 5})); + EXPECT_EQ(result, (std::vector{2, 3, 4, 5})); } TEST_F(OneOrListTest, ShouldMap) { - sb::di::OneOrList list{2}; + sb::di::OneOrList list{2}; + + std::vector result = list.map([&](const int i) { return i * 2; }); + + EXPECT_EQ(result, std::vector{4}); + list.add(3); list.add(4); list.add(5); - const std::vector result = list.map([&](const int i) { return i * 2; }); + result = list.map([&](const int i) { return i * 2; }); - EXPECT_EQ(result, (std::vector{4, 6, 8, 10})); + EXPECT_EQ(result, (std::vector{4, 6, 8, 10})); } diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 2734e45..9d2954d 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -70,7 +70,7 @@ TEST_F(ServiceDescriptorTest, ShouldGetProperInfoFromAliasDescriptor) EXPECT_EQ(descriptor.getImplementationTypeId(), typeid(TestClass1)); EXPECT_TRUE(descriptor.isAlias()); auto getFactory = [&] { auto &f = descriptor.getImplementationFactory(); }; - EXPECT_THROW((getFactory()), sb::di::NullPointerException); + EXPECT_THROW(getFactory(), sb::di::NullPointerException); EXPECT_EQ(descriptor.getCastOffset(), 2); } diff --git a/Tests/Unit/ServiceProviderTest.cpp b/Tests/Unit/ServiceProviderTest.cpp index 2cd8ed5..59f87d6 100644 --- a/Tests/Unit/ServiceProviderTest.cpp +++ b/Tests/Unit/ServiceProviderTest.cpp @@ -24,10 +24,10 @@ TEST_F(ServiceProviderTest, ShouldCreateServiceProvider) sb::di::IServiceInstanceProvider::Ptr instanceProvider = std::make_unique(); - auto providerPtr = instanceProvider.get(); + const auto providerPtr = instanceProvider.get(); sb::di::ServiceProvider provider{std::move(instanceProvider)}; - auto &options = provider.getOptions(); + const auto &options = provider.getOptions(); EXPECT_EQ(options.prebuildSingletons, false); EXPECT_EQ(options.strongDestructionOrder, false); diff --git a/Tests/Unit/Services/InPlaceServiceTest.cpp b/Tests/Unit/Services/InPlaceServiceTest.cpp index edd6742..2d2614e 100644 --- a/Tests/Unit/Services/InPlaceServiceTest.cpp +++ b/Tests/Unit/Services/InPlaceServiceTest.cpp @@ -32,7 +32,6 @@ TEST_F(InPlaceServiceTest, ShouldCreateInPlaceService) TEST_F(InPlaceServiceTest, ShouldFailReleaseInPlaceService) { - TestClass1 test; sb::di::details::services::InPlaceService service{}; EXPECT_TRUE(service.isValid()); @@ -42,7 +41,6 @@ TEST_F(InPlaceServiceTest, ShouldFailReleaseInPlaceService) TEST_F(InPlaceServiceTest, ShouldSuccedMoveOutInPlaceService) { - TestClass1 test; sb::di::details::services::InPlaceService service{}; EXPECT_TRUE(service.isValid()); diff --git a/Tests/Unit/Services/UniquePtrServiceTest.cpp b/Tests/Unit/Services/UniquePtrServiceTest.cpp index 815add2..868eed5 100644 --- a/Tests/Unit/Services/UniquePtrServiceTest.cpp +++ b/Tests/Unit/Services/UniquePtrServiceTest.cpp @@ -32,7 +32,6 @@ TEST_F(UniquePtrServiceTest, ShouldCreateUniquePtrService) TEST_F(UniquePtrServiceTest, ShouldSuccedReleasePtrService) { - TestClass1 test; sb::di::details::services::UniquePtrService service{std::make_unique()}; EXPECT_TRUE(service.isValid()); @@ -44,7 +43,6 @@ TEST_F(UniquePtrServiceTest, ShouldSuccedReleasePtrService) TEST_F(UniquePtrServiceTest, ShouldSuccedMoveOutUniquePtrService) { - TestClass1 test; sb::di::details::services::UniquePtrService service{std::make_unique()}; EXPECT_TRUE(service.isValid()); @@ -63,7 +61,6 @@ TEST_F(UniquePtrServiceTest, ShouldCreateExternalNullService) TEST_F(UniquePtrServiceTest, ShouldFailReleaseExternalNullService) { - TestClass1 test; sb::di::details::services::UniquePtrService service{nullptr}; EXPECT_FALSE(service.isValid()); @@ -73,7 +70,6 @@ TEST_F(UniquePtrServiceTest, ShouldFailReleaseExternalNullService) TEST_F(UniquePtrServiceTest, ShouldFailMoveOutExternalNullService) { - TestClass1 test; sb::di::details::services::UniquePtrService service{nullptr}; EXPECT_FALSE(service.isValid()); diff --git a/Tests/Unit/Utils/CheckBaseTest.cpp b/Tests/Unit/Utils/CheckBaseTest.cpp new file mode 100644 index 0000000..4e6507f --- /dev/null +++ b/Tests/Unit/Utils/CheckBaseTest.cpp @@ -0,0 +1,50 @@ +#include + +#include "SevenBit/DI/Details/Services/ExternalService.hpp" +#include "SevenBit/DI/Details/Utils/CheckBase.hpp" + +class CheckBaseTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + CheckBaseTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~CheckBaseTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(CheckBaseTest, ShouldCheckNotNull) +{ + EXPECT_FALSE(sb::di::details::utils::CheckBase::notNull(nullptr)); + EXPECT_FALSE(sb::di::details::utils::CheckBase::notNull(std::unique_ptr())); + EXPECT_FALSE(sb::di::details::utils::CheckBase::notNull(std::shared_ptr())); + + int intTest = 123; + EXPECT_TRUE(sb::di::details::utils::CheckBase::notNull(&intTest)); + EXPECT_TRUE(sb::di::details::utils::CheckBase::notNull(std::make_unique(intTest))); + EXPECT_TRUE(sb::di::details::utils::CheckBase::notNull(std::make_shared(intTest))); +} + +TEST_F(CheckBaseTest, ShouldCheckEnum) +{ + enum TestEnum + { + A, + B, + C, + Count, + }; + EXPECT_FALSE(sb::di::details::utils::CheckBase::enumValidity(static_cast(123))); + EXPECT_FALSE(sb::di::details::utils::CheckBase::enumValidity(static_cast(-123))); + EXPECT_FALSE(sb::di::details::utils::CheckBase::enumValidity(static_cast(-1))); + EXPECT_FALSE(sb::di::details::utils::CheckBase::enumValidity(TestEnum::Count)); + EXPECT_TRUE(sb::di::details::utils::CheckBase::enumValidity(TestEnum::A)); + EXPECT_TRUE(sb::di::details::utils::CheckBase::enumValidity(TestEnum::B)); + EXPECT_TRUE(sb::di::details::utils::CheckBase::enumValidity(TestEnum::C)); +} diff --git a/Tests/Unit/Utils/CheckTest.cpp b/Tests/Unit/Utils/CheckTest.cpp index daf61a2..fa10a19 100644 --- a/Tests/Unit/Utils/CheckTest.cpp +++ b/Tests/Unit/Utils/CheckTest.cpp @@ -1,60 +1,28 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Basic.hpp" -#include "../../Helpers/Classes/Inherit.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" +#include "SevenBit/DI/Details/Utils/Check.hpp" -class CheckTest : public testing::Test +class CheckExtTest : public testing::Test { protected: static void TearUpTestSuite() {} - CheckTest() {} + CheckExtTest() {} void SetUp() override {} void TearDown() override {} - ~CheckTest() override = default; + ~CheckExtTest() override = default; static void TearDownTestSuite() {} }; -TEST_F(CheckTest, ShouldCheckNotNull) -{ - EXPECT_FALSE(sb::di::details::utils::Check::notNull(nullptr)); - EXPECT_FALSE(sb::di::details::utils::Check::notNull(std::unique_ptr())); - EXPECT_FALSE(sb::di::details::utils::Check::notNull(std::shared_ptr())); - - int intTest = 123; - EXPECT_TRUE(sb::di::details::utils::Check::notNull(&intTest)); - EXPECT_TRUE(sb::di::details::utils::Check::notNull(std::make_unique(intTest))); - EXPECT_TRUE(sb::di::details::utils::Check::notNull(std::make_shared(intTest))); -} - -TEST_F(CheckTest, ShouldCheckEnum) -{ - enum TestEnum - { - A, - B, - C, - Count, - }; - EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(123))); - EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(-123))); - EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(static_cast(-1))); - EXPECT_FALSE(sb::di::details::utils::Check::enumValidity(TestEnum::Count)); - EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::A)); - EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::B)); - EXPECT_TRUE(sb::di::details::utils::Check::enumValidity(TestEnum::C)); -} - -TEST_F(CheckTest, ShoulCheckInstanceValidity) +TEST_F(CheckExtTest, ShoulCheckInstanceValidity) { TestClass1 test; EXPECT_FALSE(sb::di::details::utils::Check::instanceValidity(nullptr)); diff --git a/Tests/Unit/Utils/CtorParamsNumberTest.cpp b/Tests/Unit/Utils/CtorParamsNumberTest.cpp index 6915cac..260253e 100644 --- a/Tests/Unit/Utils/CtorParamsNumberTest.cpp +++ b/Tests/Unit/Utils/CtorParamsNumberTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/Details/Utils/CtorParamsNumber.hpp" diff --git a/Tests/Unit/Utils/InheritanceTest.cpp b/Tests/Unit/Utils/InheritanceTest.cpp index 616403f..3cc9324 100644 --- a/Tests/Unit/Utils/InheritanceTest.cpp +++ b/Tests/Unit/Utils/InheritanceTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "../../Helpers/Classes/MultiInherit.hpp" #include "SevenBit/DI/Details/Utils/Inheritance.hpp" diff --git a/Tests/Unit/Utils/IsCopyCtorTest.cpp b/Tests/Unit/Utils/IsCopyCtorTest.cpp index 3b4a50e..fba420d 100644 --- a/Tests/Unit/Utils/IsCopyCtorTest.cpp +++ b/Tests/Unit/Utils/IsCopyCtorTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/Details/Utils/IsCopyCtor.hpp" diff --git a/Tests/Unit/Utils/IsInPlaceObjectTest.cpp b/Tests/Unit/Utils/IsInPlaceObjectTest.cpp index e8ebab7..9c1501f 100644 --- a/Tests/Unit/Utils/IsInPlaceObjectTest.cpp +++ b/Tests/Unit/Utils/IsInPlaceObjectTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/Details/Utils/IsInPlaceObject.hpp" diff --git a/Tests/Unit/Utils/IsUniquePtrTest.cpp b/Tests/Unit/Utils/IsUniquePtrTest.cpp index 6789871..ab739c6 100644 --- a/Tests/Unit/Utils/IsUniquePtrTest.cpp +++ b/Tests/Unit/Utils/IsUniquePtrTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/Details/Utils/IsUniquePtr.hpp" diff --git a/Tests/Unit/Utils/RemoveUniquePtrTest.cpp b/Tests/Unit/Utils/RemoveUniquePtrTest.cpp index c02b8e8..46b9097 100644 --- a/Tests/Unit/Utils/RemoveUniquePtrTest.cpp +++ b/Tests/Unit/Utils/RemoveUniquePtrTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Complex.hpp" #include "SevenBit/DI/Details/Utils/RemoveUniquePtr.hpp" diff --git a/Tests/Unit/Utils/RequireBaseTest.cpp b/Tests/Unit/Utils/RequireBaseTest.cpp new file mode 100644 index 0000000..71651aa --- /dev/null +++ b/Tests/Unit/Utils/RequireBaseTest.cpp @@ -0,0 +1,66 @@ +#include + +#include "../../Helpers/Classes/Basic.hpp" +#include "SevenBit/DI/Details/Services/ExternalService.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" +#include "SevenBit/DI/Details/Utils/RequireBase.hpp" + +class RequireBaseTest : public testing::Test +{ + protected: + static void TearUpTestSuite() {} + + RequireBaseTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~RequireBaseTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(RequireBaseTest, ShouldRequireNotNull) +{ + TestClass1 test1; + std::unique_ptr testPtr{new TestClass1}; + std::shared_ptr testSPtr{new TestClass1}; + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNull(&test1)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNullAndGet(&test1)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNull(testPtr)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNullAndGet(std::move(testPtr))); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNull(testSPtr)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::notNullAndGet(std::move(testSPtr))); +} + +TEST_F(RequireBaseTest, ShouldFailRequireNotNull) +{ + std::unique_ptr testPtr; + std::unique_ptr testSPtr; + EXPECT_THROW(sb::di::details::utils::RequireBase::notNull(nullptr), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::RequireBase::notNullAndGet(nullptr), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::RequireBase::notNull(testPtr), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::RequireBase::notNullAndGet(std::move(testPtr)), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::RequireBase::notNull(testSPtr), sb::di::NullPointerException); + EXPECT_THROW(sb::di::details::utils::RequireBase::notNullAndGet(std::move(testSPtr)), sb::di::NullPointerException); +} + +TEST_F(RequireBaseTest, ShouldRequireValidEnum) +{ + enum TestEnum + { + A, + B, + C, + Count, + }; + EXPECT_THROW(sb::di::details::utils::RequireBase::validEnum(static_cast(123)), sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::RequireBase::validEnum(static_cast(-123)), + sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::RequireBase::validEnum(static_cast(-1)), sb::di::InjectorException); + EXPECT_THROW(sb::di::details::utils::RequireBase::validEnum(TestEnum::Count), sb::di::InjectorException); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::validEnum(TestEnum::A)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::validEnum(TestEnum::B)); + EXPECT_NO_THROW(sb::di::details::utils::RequireBase::validEnum(TestEnum::C)); +} diff --git a/Tests/Unit/Utils/RequireTest.cpp b/Tests/Unit/Utils/RequireTest.cpp index 0ae05af..13d9700 100644 --- a/Tests/Unit/Utils/RequireTest.cpp +++ b/Tests/Unit/Utils/RequireTest.cpp @@ -1,7 +1,5 @@ #include -#include "SevenBit/DI/Details/Utils/Check.hpp" - #include "../../Helpers/Classes/Basic.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" @@ -24,51 +22,7 @@ class RequireTest : public testing::Test static void TearDownTestSuite() {} }; -TEST_F(RequireTest, ShouldRequireNotNull) -{ - TestClass1 test1; - std::unique_ptr testPtr{new TestClass1}; - std::shared_ptr testSPtr{new TestClass1}; - EXPECT_NO_THROW(sb::di::details::utils::Require::notNull(&test1)); - EXPECT_NO_THROW(sb::di::details::utils::Require::notNullAndGet(&test1)); - EXPECT_NO_THROW(sb::di::details::utils::Require::notNull(testPtr)); - EXPECT_NO_THROW(sb::di::details::utils::Require::notNullAndGet(std::move(testPtr))); - EXPECT_NO_THROW(sb::di::details::utils::Require::notNull(testSPtr)); - EXPECT_NO_THROW(sb::di::details::utils::Require::notNullAndGet(std::move(testSPtr))); -} - -TEST_F(RequireTest, ShouldFailRequireNotNull) -{ - TestClass1 test1; - std::unique_ptr testPtr; - std::unique_ptr testSPtr; - EXPECT_THROW(sb::di::details::utils::Require::notNull(nullptr), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::notNullAndGet(nullptr), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::notNull(testPtr), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::notNullAndGet(std::move(testPtr)), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::notNull(testSPtr), sb::di::NullPointerException); - EXPECT_THROW(sb::di::details::utils::Require::notNullAndGet(std::move(testSPtr)), sb::di::NullPointerException); -} - -TEST_F(RequireTest, ShouldRequireValidEnum) -{ - enum TestEnum - { - A, - B, - C, - Count, - }; - EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(123)), sb::di::InjectorException); - EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(-123)), sb::di::InjectorException); - EXPECT_THROW(sb::di::details::utils::Require::validEnum(static_cast(-1)), sb::di::InjectorException); - EXPECT_THROW(sb::di::details::utils::Require::validEnum(TestEnum::Count), sb::di::InjectorException); - EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::A)); - EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::B)); - EXPECT_NO_THROW(sb::di::details::utils::Require::validEnum(TestEnum::C)); -} - -TEST_F(RequireTest, ShoulRequireValidInstance) +TEST_F(RequireTest, ShoulRequireExtValidInstance) { TestClass1 test; EXPECT_THROW(sb::di::details::utils::Require::validInstance(nullptr), sb::di::NullPointerException); From 20ca766a19f5a1343a3d99ca0106eb065f87a8fe Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 5 Feb 2024 17:08:20 +0100 Subject: [PATCH 37/45] add include --- Include/SevenBit/DI/OneOrList.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Include/SevenBit/DI/OneOrList.hpp b/Include/SevenBit/DI/OneOrList.hpp index c9d4ae5..8ead3e4 100644 --- a/Include/SevenBit/DI/OneOrList.hpp +++ b/Include/SevenBit/DI/OneOrList.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include From a5b996c80fc4309320d5b6369cf17d782bc06f49 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 5 Feb 2024 20:55:16 +0100 Subject: [PATCH 38/45] add factory tests --- Tests/Integration/BasicFactoryTest.cpp | 228 +++++++++++++++ Tests/Integration/InheritanceFactoryTest.cpp | 262 ++++++++++++++++++ Tests/Integration/ScopeTest.cpp | 1 - .../Containers/ServiceDescriptorsMapTest.cpp | 2 - .../Containers/ServiceInstanceListTest.cpp | 1 - .../Containers/ServiceInstancesMapTest.cpp | 1 - .../Unit/Core/ServiceInstanceCreatorTest.cpp | 2 +- .../Core/ServiceInstanceProviderRootTest.cpp | 3 +- .../Unit/Core/ServiceInstanceResolverTest.cpp | 3 +- Tests/Unit/Factories/ServiceFactoryTest.cpp | 1 - .../Unit/Factories/ServiceFcnFactoryTest.cpp | 1 - Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp | 3 +- .../Helpers/ServiceFactoryInvokerTest.cpp | 3 +- .../Unit/Helpers/ServiceParamProviderTest.cpp | 1 - Tests/Unit/ServiceDescriptorTest.cpp | 1 - Tests/Unit/Utils/CastTest.cpp | 12 +- Tests/Unit/Utils/CheckBaseTest.cpp | 1 - Tests/Unit/Utils/RequireBaseTest.cpp | 3 +- Tests/Unit/Utils/RequireTest.cpp | 1 + 19 files changed, 502 insertions(+), 28 deletions(-) create mode 100644 Tests/Integration/BasicFactoryTest.cpp create mode 100644 Tests/Integration/InheritanceFactoryTest.cpp diff --git a/Tests/Integration/BasicFactoryTest.cpp b/Tests/Integration/BasicFactoryTest.cpp new file mode 100644 index 0000000..9f79953 --- /dev/null +++ b/Tests/Integration/BasicFactoryTest.cpp @@ -0,0 +1,228 @@ +#include +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "../Helpers/Classes/CirularDependency.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class BasicFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + BasicFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~BasicFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +// buildServiceProvider Tests + +TEST_F(BasicFactoryTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return TestClass1{}; }); + collection.addSingleton([] { return TestClass1{}; }); + collection.addSingleton([] { return TestClass2{}; }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(BasicFactoryTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return TestClass1{}; }); + collection.addSingleton([] { return TestClass1{}; }); + collection.addSingleton([] { return TestClass2{}; }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +// tryGetService Tests + +TEST_F(BasicFactoryTest, ShouldTryGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_TRUE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(BasicFactoryTest, ShouldFailTryGetServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return CircularDependencyA{b}; }) + .addScoped([](CircularDependencyA *a) { return CircularDependencyB{a}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.tryGetService(), sb::di::CircularDependencyException); +} + +// getService Tests + +TEST_F(BasicFactoryTest, ShouldGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_NO_THROW(provider.getService()); + EXPECT_NO_THROW(provider.getService()); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} +TEST_F(BasicFactoryTest, ShouldFailGetServiceDueToCircularDependency) +{ + + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return CircularDependencyA{b}; }) + .addScoped([](CircularDependencyA *a) { return CircularDependencyB{a}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.getService(), sb::di::CircularDependencyException); +} + +// getServices Tests + +TEST_F(BasicFactoryTest, ShouldFailGetServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return CircularDependencyA{b}; }) + .addScoped([](CircularDependencyA *a) { return CircularDependencyB{a}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.getServices(), sb::di::CircularDependencyException); +} + +// tryCreateService Tests + +TEST_F(BasicFactoryTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_TRUE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(BasicFactoryTest, ShouldFailTryCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return CircularDependencyUniqueA{std::move(b)}; + }) + .addTransient([](std::unique_ptr a) { + return CircularDependencyUniqueB{std::move(a)}; + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.tryCreateService(), sb::di::CircularDependencyException); +} + +// createService Tests + +TEST_F(BasicFactoryTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createService()); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicFactoryTest, ShouldFailCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return CircularDependencyUniqueA{std::move(b)}; + }) + .addTransient([](std::unique_ptr a) { + return CircularDependencyUniqueB{std::move(a)}; + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::CircularDependencyException); +} + +TEST_F(BasicFactoryTest, ShouldNotCreateSelfService) +{ + auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +// createServiceInPlace Tests + +TEST_F(BasicFactoryTest, ShouldCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createServiceInPlace()); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicFactoryTest, ShouldFailCreateServiceInPlaceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return CircularDependencyUniqueA{std::move(b)}; + }) + .addTransient([](std::unique_ptr a) { + return CircularDependencyUniqueB{std::move(a)}; + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::CircularDependencyException); +} + +// createServices Tests + +TEST_F(BasicFactoryTest, ShouldFaildCreateServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return CircularDependencyUniqueA{std::move(b)}; + }) + .addTransient([](std::unique_ptr a) { + return CircularDependencyUniqueB{std::move(a)}; + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServices(), sb::di::CircularDependencyException); +} diff --git a/Tests/Integration/InheritanceFactoryTest.cpp b/Tests/Integration/InheritanceFactoryTest.cpp new file mode 100644 index 0000000..2cb920e --- /dev/null +++ b/Tests/Integration/InheritanceFactoryTest.cpp @@ -0,0 +1,262 @@ +#include +#include + +#include "../Helpers/Classes/Inherit.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class InheritanceFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + InheritanceFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~InheritanceFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(InheritanceFactoryTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return TestInheritClass2{}; }); + collection.addSingleton([] { return TestInheritClass2{}; }); + collection.addSingleton([] { return TestInheritClass4{}; }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(InheritanceFactoryTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return TestInheritClass2{}; }); + collection.addSingleton([] { return TestInheritClass2{}; }); + collection.addSingleton([] { return TestInheritClass4{}; }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +TEST_F(InheritanceFactoryTest, ShouldFailGetServiceDueToLifetimeMissmatchService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return TestInheritClass3{}; }); + collection.addSingleton([] { return TestInheritClass5{}; }); + collection.addTransient([] { return TestInheritClass4{}; }); + + EXPECT_THROW(collection.buildServiceProvider(), sb::di::ServiceLifeTimeMismatchException); +} + +TEST_F(InheritanceFactoryTest, ShouldTryGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_TRUE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(InheritanceFactoryTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addSingleton([] { return TestInheritClass3{}; }) + .addSingleton([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_EQ(provider.tryGetService()->number(), 5); +} + +TEST_F(InheritanceFactoryTest, ShouldTryGetOneLastServiceScope) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addScoped([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_EQ(provider.tryGetService()->number(), 5); +} + +TEST_F(InheritanceFactoryTest, ShouldGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_NO_THROW(provider.getService()); + EXPECT_NO_THROW(provider.getService()); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceFactoryTest, ShouldGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addSingleton([] { return TestInheritClass3{}; }) + .addSingleton([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getService().number(), 5); +} + +TEST_F(InheritanceFactoryTest, ShouldGetOneLastServiceScope) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addScoped([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getService().number(), 5); +} + +TEST_F(InheritanceFactoryTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); +} + +TEST_F(InheritanceFactoryTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass1{}; }) + .addScoped([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addScoped([] { return TestInheritClass4{}; }) + .addScoped([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); +} + +TEST_F(InheritanceFactoryTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass1{}; }) + .addScoped([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addScoped([] { return TestInheritClass4{}; }) + .addScoped([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); + EXPECT_TRUE(provider.tryGetService()); +} + +TEST_F(InheritanceFactoryTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_TRUE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(InheritanceFactoryTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createService()); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceFactoryTest, ShouldCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceFactoryTest, ShouldCreateServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestInheritClass2{}; }) + .addScoped([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(InheritanceFactoryTest, ShouldCreateServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([] { return TestInheritClass1{}; }) + .addTransient([] { return TestInheritClass2{}; }) + .addTransient([] { return TestInheritClass3{}; }) + .addTransient([] { return TestInheritClass4{}; }) + .addTransient([] { return TestInheritClass5{}; }) + .buildServiceProvider(); + + const auto services = provider.createServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); +} diff --git a/Tests/Integration/ScopeTest.cpp b/Tests/Integration/ScopeTest.cpp index a8f1d91..217e330 100644 --- a/Tests/Integration/ScopeTest.cpp +++ b/Tests/Integration/ScopeTest.cpp @@ -5,7 +5,6 @@ #include "../Helpers/Classes/Complex.hpp" #include "../Helpers/Classes/Dependencies.hpp" #include "SevenBit/DI/ServiceCollection.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" class ScopeTest : public testing::Test { diff --git a/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp b/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp index ffbdfc3..1afe2c9 100644 --- a/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp +++ b/Tests/Unit/Containers/ServiceDescriptorsMapTest.cpp @@ -3,8 +3,6 @@ #include "../../Helpers/Classes/Inherit.hpp" #include "SevenBit/DI/Details/Containers/ServiceDescriptorsMap.hpp" #include "SevenBit/DI/ServiceDescriber.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" class ServiceDescriptorsMapTest : public testing::Test { diff --git a/Tests/Unit/Containers/ServiceInstanceListTest.cpp b/Tests/Unit/Containers/ServiceInstanceListTest.cpp index b9ce038..6f8759c 100644 --- a/Tests/Unit/Containers/ServiceInstanceListTest.cpp +++ b/Tests/Unit/Containers/ServiceInstanceListTest.cpp @@ -7,7 +7,6 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceInstance.hpp" class ServiceInstanceListTest : public testing::Test { diff --git a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp index 32646b1..55fee42 100644 --- a/Tests/Unit/Containers/ServiceInstancesMapTest.cpp +++ b/Tests/Unit/Containers/ServiceInstancesMapTest.cpp @@ -8,7 +8,6 @@ #include "SevenBit/DI/Details/Containers/ServiceInstancesMap.hpp" #include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/ServiceDescriber.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" class ServiceInstancesMapTest : public testing::Test { diff --git a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp index 3e1ff8b..c90afd5 100644 --- a/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceCreatorTest.cpp @@ -7,7 +7,7 @@ #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceCreator.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceCollection.hpp" +#include "SevenBit/DI/ServiceDescriber.hpp" class ServiceInstanceCreatorTest : public testing::Test { diff --git a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp index 9b9fc9a..a532371 100644 --- a/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceProviderRootTest.cpp @@ -4,10 +4,9 @@ #include "../../Helpers/Classes/Basic.hpp" #include "../../Helpers/Classes/Inherit.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Core/ServiceInstanceProvider.hpp" #include "SevenBit/DI/Details/Core/ServiceInstanceProviderRoot.hpp" #include "SevenBit/DI/Exceptions.hpp" -#include "SevenBit/DI/ServiceCollection.hpp" +#include "SevenBit/DI/ServiceDescriber.hpp" class ServiceInstanceProviderRootTest : public testing::Test { diff --git a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp index 304a15c..5e0fd88 100644 --- a/Tests/Unit/Core/ServiceInstanceResolverTest.cpp +++ b/Tests/Unit/Core/ServiceInstanceResolverTest.cpp @@ -4,9 +4,8 @@ #include "../../Helpers/Classes/Basic.hpp" #include "../../Helpers/Classes/Inherit.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Containers/ServiceDescriptorList.hpp" #include "SevenBit/DI/Details/Core/ServiceInstancesResolver.hpp" -#include "SevenBit/DI/ServiceCollection.hpp" +#include "SevenBit/DI/ServiceDescriber.hpp" class ServiceInstanceResolverTest : public testing::Test { diff --git a/Tests/Unit/Factories/ServiceFactoryTest.cpp b/Tests/Unit/Factories/ServiceFactoryTest.cpp index 7d4adae..53d9f5d 100644 --- a/Tests/Unit/Factories/ServiceFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFactoryTest.cpp @@ -5,7 +5,6 @@ #include "../../Helpers/Classes/Dependencies.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" class ServiceFactoryTest : public testing::Test { diff --git a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp index 9c2b4e2..826f88a 100644 --- a/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp +++ b/Tests/Unit/Factories/ServiceFcnFactoryTest.cpp @@ -5,7 +5,6 @@ #include "../../Helpers/Classes/Dependencies.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" #include "SevenBit/DI/Details/Factories/ServiceFcnFactory.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" class ServiceFcnFactoryTest : public testing::Test { diff --git a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp index 8bf10d8..4edf663 100644 --- a/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceCtorInvokerTest.cpp @@ -2,9 +2,8 @@ #include "../../Helpers/Classes/Dependencies.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Helpers/ServiceCtorInvoker.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" class ServiceCtorInvokerTest : public testing::Test { diff --git a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp index c7e3088..1f13ad9 100644 --- a/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp +++ b/Tests/Unit/Helpers/ServiceFactoryInvokerTest.cpp @@ -2,9 +2,8 @@ #include "../../Helpers/Classes/Dependencies.hpp" #include "../../Helpers/Mocks/ServiceProviderMock.hpp" -#include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Details/Helpers/ServiceFactoryInvoker.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" +#include "SevenBit/DI/Details/Services/InPlaceService.hpp" class ServiceFactoryInvokerTest : public testing::Test { diff --git a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp index b8ca5f6..47cb8ee 100644 --- a/Tests/Unit/Helpers/ServiceParamProviderTest.cpp +++ b/Tests/Unit/Helpers/ServiceParamProviderTest.cpp @@ -5,7 +5,6 @@ #include "SevenBit/DI/Details/Helpers/ServiceParamProvider.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" -#include "SevenBit/DI/ServiceProvider.hpp" class ServiceParamProviderTest : public testing::Test { diff --git a/Tests/Unit/ServiceDescriptorTest.cpp b/Tests/Unit/ServiceDescriptorTest.cpp index 9d2954d..3bb436a 100644 --- a/Tests/Unit/ServiceDescriptorTest.cpp +++ b/Tests/Unit/ServiceDescriptorTest.cpp @@ -6,7 +6,6 @@ #include "SevenBit/DI/Details/Factories/ServiceFactory.hpp" #include "SevenBit/DI/Exceptions.hpp" #include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" class ServiceDescriptorTest : public testing::Test { diff --git a/Tests/Unit/Utils/CastTest.cpp b/Tests/Unit/Utils/CastTest.cpp index 9057bf5..6c8e7ee 100644 --- a/Tests/Unit/Utils/CastTest.cpp +++ b/Tests/Unit/Utils/CastTest.cpp @@ -1,10 +1,8 @@ #include -#include "SevenBit/DI/Details/Utils/Cast.hpp" - #include "../../Helpers/Classes/MultiInherit.hpp" -#include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Services/InPlaceService.hpp" +#include "SevenBit/DI/Details/Utils/Cast.hpp" class CastTest : public testing::Test { @@ -49,11 +47,11 @@ TEST_F(CastTest, ShouldGetCastOffset) TEST_F(CastTest, ShouldApplyCastOffset) { EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(1), 0)), - reinterpret_cast(1)); + reinterpret_cast(1)); EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(1), 1)), - reinterpret_cast(2)); + reinterpret_cast(2)); EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(22), 11)), - reinterpret_cast(33)); + reinterpret_cast(33)); EXPECT_EQ((sb::di::details::utils::Cast::applyCastOffset(reinterpret_cast(22), -11)), - reinterpret_cast(11)); + reinterpret_cast(11)); } diff --git a/Tests/Unit/Utils/CheckBaseTest.cpp b/Tests/Unit/Utils/CheckBaseTest.cpp index 4e6507f..1cefb3c 100644 --- a/Tests/Unit/Utils/CheckBaseTest.cpp +++ b/Tests/Unit/Utils/CheckBaseTest.cpp @@ -1,6 +1,5 @@ #include -#include "SevenBit/DI/Details/Services/ExternalService.hpp" #include "SevenBit/DI/Details/Utils/CheckBase.hpp" class CheckBaseTest : public testing::Test diff --git a/Tests/Unit/Utils/RequireBaseTest.cpp b/Tests/Unit/Utils/RequireBaseTest.cpp index 71651aa..c8f2e4d 100644 --- a/Tests/Unit/Utils/RequireBaseTest.cpp +++ b/Tests/Unit/Utils/RequireBaseTest.cpp @@ -1,9 +1,8 @@ #include #include "../../Helpers/Classes/Basic.hpp" -#include "SevenBit/DI/Details/Services/ExternalService.hpp" -#include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Utils/RequireBase.hpp" +#include "SevenBit/DI/Exceptions.hpp" class RequireBaseTest : public testing::Test { diff --git a/Tests/Unit/Utils/RequireTest.cpp b/Tests/Unit/Utils/RequireTest.cpp index 13d9700..7c6ae89 100644 --- a/Tests/Unit/Utils/RequireTest.cpp +++ b/Tests/Unit/Utils/RequireTest.cpp @@ -5,6 +5,7 @@ #include "SevenBit/DI/Details/Services/InPlaceService.hpp" #include "SevenBit/DI/Details/Services/UniquePtrService.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" +#include "SevenBit/DI/Exceptions.hpp" class RequireTest : public testing::Test { From e681b66d295f140f8e23ab1fe4c6b2c54ce069b4 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Mon, 5 Feb 2024 21:16:54 +0100 Subject: [PATCH 39/45] add uniq factory tests --- Tests/Integration/BasicFactoryTest.cpp | 7 - Tests/Integration/BasicUniqFactoryTest.cpp | 221 +++++++++++++++ .../InheritanceUniqFactoryTest.cpp | 262 ++++++++++++++++++ 3 files changed, 483 insertions(+), 7 deletions(-) create mode 100644 Tests/Integration/BasicUniqFactoryTest.cpp create mode 100644 Tests/Integration/InheritanceUniqFactoryTest.cpp diff --git a/Tests/Integration/BasicFactoryTest.cpp b/Tests/Integration/BasicFactoryTest.cpp index 9f79953..b10f65f 100644 --- a/Tests/Integration/BasicFactoryTest.cpp +++ b/Tests/Integration/BasicFactoryTest.cpp @@ -174,13 +174,6 @@ TEST_F(BasicFactoryTest, ShouldFailCreateServiceDueToCircularDependency) EXPECT_THROW(provider.createService(), sb::di::CircularDependencyException); } -TEST_F(BasicFactoryTest, ShouldNotCreateSelfService) -{ - auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); - - EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); -} - // createServiceInPlace Tests TEST_F(BasicFactoryTest, ShouldCreateServiceInPlace) diff --git a/Tests/Integration/BasicUniqFactoryTest.cpp b/Tests/Integration/BasicUniqFactoryTest.cpp new file mode 100644 index 0000000..c9ec47c --- /dev/null +++ b/Tests/Integration/BasicUniqFactoryTest.cpp @@ -0,0 +1,221 @@ +#include +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "../Helpers/Classes/CirularDependency.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class BasicUniqFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + BasicUniqFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~BasicUniqFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +// buildServiceProvider Tests + +TEST_F(BasicUniqFactoryTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(BasicUniqFactoryTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +// tryGetService Tests + +TEST_F(BasicUniqFactoryTest, ShouldTryGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_TRUE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(BasicUniqFactoryTest, ShouldFailTryGetServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return std::make_unique(b); }) + .addScoped([](CircularDependencyA *a) { return std::make_unique(a); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.tryGetService(), sb::di::CircularDependencyException); +} + +// getService Tests + +TEST_F(BasicUniqFactoryTest, ShouldGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_NO_THROW(provider.getService()); + EXPECT_NO_THROW(provider.getService()); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} +TEST_F(BasicUniqFactoryTest, ShouldFailGetServiceDueToCircularDependency) +{ + + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return std::make_unique(b); }) + .addScoped([](CircularDependencyA *a) { return std::make_unique(a); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.getService(), sb::di::CircularDependencyException); +} + +// getServices Tests + +TEST_F(BasicUniqFactoryTest, ShouldFailGetServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([](CircularDependencyB *b) { return std::make_unique(b); }) + .addScoped([](CircularDependencyA *a) { return std::make_unique(a); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.getServices(), sb::di::CircularDependencyException); +} + +// tryCreateService Tests + +TEST_F(BasicUniqFactoryTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_TRUE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(BasicUniqFactoryTest, ShouldFailTryCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return std::make_unique(std::move(b)); + }) + .addTransient([](std::unique_ptr a) { + return std::make_unique(std::move(a)); + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.tryCreateService(), sb::di::CircularDependencyException); +} + +// createService Tests + +TEST_F(BasicUniqFactoryTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createService()); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicUniqFactoryTest, ShouldFailCreateServiceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return std::make_unique(std::move(b)); + }) + .addTransient([](std::unique_ptr a) { + return std::make_unique(std::move(a)); + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::CircularDependencyException); +} + +// createServiceInPlace Tests + +TEST_F(BasicUniqFactoryTest, ShouldCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createServiceInPlace()); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicUniqFactoryTest, ShouldFailCreateServiceInPlaceDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return std::make_unique(std::move(b)); + }) + .addTransient([](std::unique_ptr a) { + return std::make_unique(std::move(a)); + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::CircularDependencyException); +} + +// createServices Tests + +TEST_F(BasicUniqFactoryTest, ShouldFaildCreateServicesDueToCircularDependency) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([](std::unique_ptr b) { + return std::make_unique(std::move(b)); + }) + .addTransient([](std::unique_ptr a) { + return std::make_unique(std::move(a)); + }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServices(), sb::di::CircularDependencyException); +} diff --git a/Tests/Integration/InheritanceUniqFactoryTest.cpp b/Tests/Integration/InheritanceUniqFactoryTest.cpp new file mode 100644 index 0000000..911b1da --- /dev/null +++ b/Tests/Integration/InheritanceUniqFactoryTest.cpp @@ -0,0 +1,262 @@ +#include +#include + +#include "../Helpers/Classes/Inherit.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class InheritanceUniqFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + InheritanceUniqFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~InheritanceUniqFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(InheritanceUniqFactoryTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldFailGetServiceDueToLifetimeMissmatchService) +{ + sb::di::ServiceCollection collection; + + collection.addSingleton([] { return std::make_unique(); }); + collection.addSingleton([] { return std::make_unique(); }); + collection.addTransient([] { return std::make_unique(); }); + + EXPECT_THROW(collection.buildServiceProvider(), sb::di::ServiceLifeTimeMismatchException); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldTryGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_TRUE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_EQ(provider.tryGetService()->number(), 5); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldTryGetOneLastServiceScope) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_EQ(provider.tryGetService()->number(), 5); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_NO_THROW(provider.getService()); + EXPECT_NO_THROW(provider.getService()); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getService().number(), 5); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetOneLastServiceScope) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getService().number(), 5); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass1{}; }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestInheritClass1{}; }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); + EXPECT_TRUE(provider.tryGetService()); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldTryCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_TRUE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldCreateService) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_NO_THROW(provider.createService()); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldCreateServiceInPlace) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldCreateServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(InheritanceUniqFactoryTest, ShouldCreateServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([] { return TestInheritClass1{}; }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto services = provider.createServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0]->number(), 1); + EXPECT_EQ(services[1]->number(), 2); + EXPECT_EQ(services[2]->number(), 3); + EXPECT_EQ(services[3]->number(), 4); + EXPECT_EQ(services[4]->number(), 5); +} From 81eb4f3b00d179db51c19a887a1e1a21e5298fb7 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 6 Feb 2024 18:21:40 +0100 Subject: [PATCH 40/45] add more integration tests --- Tests/Integration/BasicExternalTest.cpp | 186 ++++++++++ Tests/Integration/BasicFactoryTest.cpp | 26 ++ Tests/Integration/BasicTest.cpp | 26 ++ Tests/Integration/BasicUniqFactoryTest.cpp | 26 ++ Tests/Integration/InheritanceExternalTest.cpp | 278 ++++++++++++++ Tests/Integration/InjectionTest.cpp | 2 +- .../MultiInheritanceExternalTest.cpp | 278 ++++++++++++++ .../MultiInheritanceFactoryTest.cpp | 329 +++++++++++++++++ .../MultiInheritanceUniqFactoryTest.cpp | 339 ++++++++++++++++++ 9 files changed, 1489 insertions(+), 1 deletion(-) create mode 100644 Tests/Integration/BasicExternalTest.cpp create mode 100644 Tests/Integration/InheritanceExternalTest.cpp create mode 100644 Tests/Integration/MultiInheritanceExternalTest.cpp create mode 100644 Tests/Integration/MultiInheritanceFactoryTest.cpp create mode 100644 Tests/Integration/MultiInheritanceUniqFactoryTest.cpp diff --git a/Tests/Integration/BasicExternalTest.cpp b/Tests/Integration/BasicExternalTest.cpp new file mode 100644 index 0000000..8d215ab --- /dev/null +++ b/Tests/Integration/BasicExternalTest.cpp @@ -0,0 +1,186 @@ +#include +#include + +#include "../Helpers/Classes/Basic.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class BasicExternalTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + BasicExternalTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~BasicExternalTest() override = default; + + static void TearDownTestSuite() {} +}; + +// buildServiceProvider Tests + +TEST_F(BasicExternalTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + TestClass1 test1; + TestClass2 test2; + collection.addSingleton(&test1); + collection.addSingleton(&test1); + collection.addSingleton(&test2); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(BasicExternalTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + TestClass1 test1; + TestClass2 test2; + collection.addSingleton(&test1); + collection.addSingleton(&test1); + collection.addSingleton(&test2); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +// tryGetService Tests + +TEST_F(BasicExternalTest, ShouldTryGetService) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_EQ(provider.tryGetService(), &test1); + EXPECT_EQ(provider.tryGetService(), &test2); + EXPECT_EQ(provider.tryGetService(), &test3); + EXPECT_FALSE(provider.tryGetService()); +} + +// getService Tests + +TEST_F(BasicExternalTest, ShouldGetService) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_EQ(&provider.getService(), &test1); + EXPECT_EQ(&provider.getService(), &test2); + EXPECT_EQ(&provider.getService(), &test3); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} + +TEST_F(BasicExternalTest, ShouldGetServices) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test2); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test3); +} + +// tryCreateService Tests + +TEST_F(BasicExternalTest, ShouldTryCreateService) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +// createService Tests + +TEST_F(BasicExternalTest, ShouldCreateService) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +// createServiceInPlace Tests + +TEST_F(BasicExternalTest, ShouldCreateServiceInPlace) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +// createServices Tests + +TEST_F(BasicExternalTest, ShouldCreateServices) +{ + TestClass1 test1; + TestClass2 test2; + TestClass3 test3; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .buildServiceProvider(); + + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 0); +} diff --git a/Tests/Integration/BasicFactoryTest.cpp b/Tests/Integration/BasicFactoryTest.cpp index b10f65f..884232b 100644 --- a/Tests/Integration/BasicFactoryTest.cpp +++ b/Tests/Integration/BasicFactoryTest.cpp @@ -104,6 +104,19 @@ TEST_F(BasicFactoryTest, ShouldFailGetServiceDueToCircularDependency) // getServices Tests +TEST_F(BasicFactoryTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 0); +} + TEST_F(BasicFactoryTest, ShouldFailGetServicesDueToCircularDependency) { auto provider = sb::di::ServiceCollection{} @@ -206,6 +219,19 @@ TEST_F(BasicFactoryTest, ShouldFailCreateServiceInPlaceDueToCircularDependency) // createServices Tests +TEST_F(BasicFactoryTest, ShouldCreateServicess) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestClass1{}; }) + .addScoped([] { return TestClass2{}; }) + .addTransient([] { return TestClass3{}; }) + .buildServiceProvider(); + + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 1); +} + TEST_F(BasicFactoryTest, ShouldFaildCreateServicesDueToCircularDependency) { auto provider = sb::di::ServiceCollection{} diff --git a/Tests/Integration/BasicTest.cpp b/Tests/Integration/BasicTest.cpp index 0571c27..ed772c8 100644 --- a/Tests/Integration/BasicTest.cpp +++ b/Tests/Integration/BasicTest.cpp @@ -121,6 +121,19 @@ TEST_F(BasicTest, ShouldGetSelf) // getServices Tests +TEST_F(BasicTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 0); +} + TEST_F(BasicTest, ShouldGetEmptyServicesForNotExisting) { auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); @@ -242,6 +255,19 @@ TEST_F(BasicTest, ShouldFailCreateServiceInPlaceDueToCircularDependency) // createServices Tests +TEST_F(BasicTest, ShouldCreateServicess) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton() + .addScoped() + .addTransient() + .buildServiceProvider(); + + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 1); +} + TEST_F(BasicTest, ShouldCreateEmptyServicesForNotExisting) { auto provider = sb::di::ServiceCollection{}.buildServiceProvider(); diff --git a/Tests/Integration/BasicUniqFactoryTest.cpp b/Tests/Integration/BasicUniqFactoryTest.cpp index c9ec47c..3849872 100644 --- a/Tests/Integration/BasicUniqFactoryTest.cpp +++ b/Tests/Integration/BasicUniqFactoryTest.cpp @@ -104,6 +104,19 @@ TEST_F(BasicUniqFactoryTest, ShouldFailGetServiceDueToCircularDependency) // getServices Tests +TEST_F(BasicUniqFactoryTest, ShouldGetServices) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 0); +} + TEST_F(BasicUniqFactoryTest, ShouldFailGetServicesDueToCircularDependency) { auto provider = sb::di::ServiceCollection{} @@ -206,6 +219,19 @@ TEST_F(BasicUniqFactoryTest, ShouldFailCreateServiceInPlaceDueToCircularDependen // createServices Tests +TEST_F(BasicUniqFactoryTest, ShouldCreateServicess) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 0); + EXPECT_EQ(provider.createServices().size(), 1); +} + TEST_F(BasicUniqFactoryTest, ShouldFaildCreateServicesDueToCircularDependency) { auto provider = sb::di::ServiceCollection{} diff --git a/Tests/Integration/InheritanceExternalTest.cpp b/Tests/Integration/InheritanceExternalTest.cpp new file mode 100644 index 0000000..f9082d7 --- /dev/null +++ b/Tests/Integration/InheritanceExternalTest.cpp @@ -0,0 +1,278 @@ +#include +#include + +#include "../Helpers/Classes/Inherit.hpp" +#include "SevenBit/DI/Exceptions.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class InheritanceExternalTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + InheritanceExternalTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~InheritanceExternalTest() override = default; + + static void TearDownTestSuite() {} +}; + +// buildServiceProvider Tests + +TEST_F(InheritanceExternalTest, ShouldFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + TestInheritClass2 test2; + TestInheritClass4 test4; + collection.addSingleton(&test2); + collection.addSingleton(&test2); + collection.addSingleton(&test4); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = true; + EXPECT_THROW(collection.buildServiceProvider(options), sb::di::ServiceAlreadyRegisteredException); +} + +TEST_F(InheritanceExternalTest, ShouldNotFailGetServiceDueToAlreadyRegisteredService) +{ + sb::di::ServiceCollection collection; + + TestInheritClass2 test2; + TestInheritClass4 test4; + collection.addSingleton(&test2); + collection.addSingleton(&test2); + collection.addSingleton(&test4); + + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + EXPECT_NO_THROW(collection.buildServiceProvider(options)); +} + +// tryGetService Tests + +TEST_F(InheritanceExternalTest, ShouldTryGetService) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(provider.tryGetService(), &test2); + EXPECT_EQ(provider.tryGetService(), &test3); + EXPECT_EQ(provider.tryGetService(), &test4); + EXPECT_FALSE(provider.tryGetService()); +} + +TEST_F(InheritanceExternalTest, ShouldTryGetOneLastServiceSingleton) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + EXPECT_EQ(provider.tryGetService(), &test4); +} + +// getService Tests + +TEST_F(InheritanceExternalTest, ShouldGetService) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(&provider.getService(), &test2); + EXPECT_EQ(&provider.getService(), &test3); + EXPECT_EQ(&provider.getService(), &test4); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceExternalTest, ShouldGetOneLastServiceSingleton) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(&provider.getService(), &test4); +} + +TEST_F(InheritanceExternalTest, ShouldGetServices) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test2); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test3); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test4); + + EXPECT_TRUE(provider.getServices().empty()); +} + +TEST_F(InheritanceExternalTest, ShouldGetCastedServicesInOrder) +{ + TestInheritClass1 test1; + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + TestInheritClass5 test5; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test5) + .buildServiceProvider(); + + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0], &test1); + EXPECT_EQ(services[1], &test2); + EXPECT_EQ(services[2], &test3); + EXPECT_EQ(services[3], &test4); + EXPECT_EQ(services[4], &test5); +} + +TEST_F(InheritanceExternalTest, ShouldGetServicesInOrderAfterNormalGet) +{ + TestInheritClass1 test1; + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + TestInheritClass5 test5; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test5) + .buildServiceProvider(); + + EXPECT_EQ(provider.tryGetService(), &test5); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 5); + EXPECT_EQ(services[0], &test1); + EXPECT_EQ(services[1], &test2); + EXPECT_EQ(services[2], &test3); + EXPECT_EQ(services[3], &test4); + EXPECT_EQ(services[4], &test5); +} + +TEST_F(InheritanceExternalTest, ShouldTryCreateService) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(InheritanceExternalTest, ShouldCreateService) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceExternalTest, ShouldCreateServiceInPlace) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(InheritanceExternalTest, ShouldCreateServices) +{ + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(InheritanceExternalTest, ShouldCreateServicesInOrder) +{ + TestInheritClass1 test1; + TestInheritClass2 test2; + TestInheritClass3 test3; + TestInheritClass4 test4; + TestInheritClass5 test5; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test1) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test5) + .buildServiceProvider(); + + const auto services = provider.createServices(); + EXPECT_TRUE(services.empty()); +} diff --git a/Tests/Integration/InjectionTest.cpp b/Tests/Integration/InjectionTest.cpp index 7fe0228..d64a87a 100644 --- a/Tests/Integration/InjectionTest.cpp +++ b/Tests/Integration/InjectionTest.cpp @@ -69,6 +69,6 @@ TEST_F(InjectionTest, ShouldTryGetDeepNestedService) auto provider = collection.buildServiceProvider(); - auto nested = provider.getService>(); + auto &nested = provider.getService>(); nested.checkRecurse(provider); } diff --git a/Tests/Integration/MultiInheritanceExternalTest.cpp b/Tests/Integration/MultiInheritanceExternalTest.cpp new file mode 100644 index 0000000..3de2861 --- /dev/null +++ b/Tests/Integration/MultiInheritanceExternalTest.cpp @@ -0,0 +1,278 @@ +#include +#include + +#include "../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class MultiInheritanceExternalTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + MultiInheritanceExternalTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~MultiInheritanceExternalTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(MultiInheritanceExternalTest, ShouldTryGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_EQ(provider.tryGetService(), &test2); + EXPECT_EQ(provider.tryGetService(), &test2); + EXPECT_EQ(provider.tryGetService(), &test3); + EXPECT_EQ(provider.tryGetService(), &test3); + EXPECT_EQ(provider.tryGetService(), &test4); + EXPECT_EQ(provider.tryGetService(), &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldTryGetOneLastServiceSingleton) +{ + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service, &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_EQ(&provider.getService(), &test2); + EXPECT_EQ(&provider.getService(), &test2); + EXPECT_EQ(&provider.getService(), &test3); + EXPECT_EQ(&provider.getService(), &test3); + EXPECT_EQ(&provider.getService(), &test4); + EXPECT_EQ(&provider.getService(), &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldGetOneLastServiceSingleton) +{ + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(&provider.getService(), &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldGetServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test2); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test2); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test3); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test3); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test4); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices()[0], &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldGetCastedServicesInOrder) +{ + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + const auto services = provider.getServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0], &test2); + EXPECT_EQ(services[1], &test3); + EXPECT_EQ(services[2], &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldGetServicesInOrderAfterNormalGet) +{ + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_EQ(provider.tryGetService(), &test4); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0], &test2); + EXPECT_EQ(services[1], &test3); + EXPECT_EQ(services[2], &test4); +} + +TEST_F(MultiInheritanceExternalTest, ShouldTryCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(MultiInheritanceExternalTest, ShouldCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceExternalTest, ShouldNotCreateServiceInPlace) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceExternalTest, ShouldCreateServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test3) + .addSingleton(&test4) + .addSingleton(&test4) + .buildServiceProvider(options); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(MultiInheritanceExternalTest, ShouldCreateServicesInOrder) +{ + TestMultiInheritClass2 test2; + TestMultiInheritClass3 test3; + TestMultiInheritClass4 test4; + auto provider = sb::di::ServiceCollection{} + .addSingleton(&test2) + .addSingleton(&test3) + .addSingleton(&test4) + .buildServiceProvider(); + + EXPECT_TRUE(provider.createServices().empty()); +} diff --git a/Tests/Integration/MultiInheritanceFactoryTest.cpp b/Tests/Integration/MultiInheritanceFactoryTest.cpp new file mode 100644 index 0000000..91d7a2f --- /dev/null +++ b/Tests/Integration/MultiInheritanceFactoryTest.cpp @@ -0,0 +1,329 @@ +#include +#include + +#include "../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class MultiInheritanceFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + MultiInheritanceFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~MultiInheritanceFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(MultiInheritanceFactoryTest, ShouldTryGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + auto service1 = provider.tryGetService(); + auto service2 = provider.tryGetService(); + auto service5 = provider.tryGetService(); + auto service6 = provider.tryGetService(); + + EXPECT_TRUE(service1); + EXPECT_TRUE(service2); + EXPECT_TRUE(service5); + EXPECT_TRUE(service6); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_EQ(service1->first(), 2); + EXPECT_EQ(service1->arr[0], 1); + EXPECT_EQ(service1->arr[8], 9); + EXPECT_EQ(service1->end, 1); + EXPECT_EQ(service2->second(), 22); + EXPECT_EQ(service2->arr[0], 1); + EXPECT_EQ(service2->arr[8], 9); + EXPECT_EQ(service2->end, 2); + EXPECT_EQ(service5->second(), 44); + EXPECT_EQ(service5->third(), 444); + EXPECT_EQ(service5->arr[0], 1); + EXPECT_EQ(service5->arr[8], 9); + EXPECT_EQ(service5->end, 5); + EXPECT_EQ(service6->fourth(), 4444); + EXPECT_EQ(service6->arr[0], 1); + EXPECT_EQ(service6->arr[8], 9); + EXPECT_EQ(service6->end, 6); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass3{}; }) + .addSingleton([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldTryGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestMultiInheritClass2{}; }) + .addScoped([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + auto &service5 = provider.getService(); + auto &service6 = provider.getService(); + + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_EQ(service1.first(), 2); + EXPECT_EQ(service1.arr[0], 1); + EXPECT_EQ(service1.arr[8], 9); + EXPECT_EQ(service1.end, 1); + EXPECT_EQ(service2.second(), 22); + EXPECT_EQ(service2.arr[0], 1); + EXPECT_EQ(service2.arr[8], 9); + EXPECT_EQ(service2.end, 2); + EXPECT_EQ(service5.first(), 4); + EXPECT_EQ(service5.second(), 44); + EXPECT_EQ(service5.third(), 444); + EXPECT_EQ(service5.arr[0], 1); + EXPECT_EQ(service5.arr[8], 9); + EXPECT_EQ(service5.end, 5); + EXPECT_EQ(service6.fourth(), 4444); + EXPECT_EQ(service6.arr[0], 1); + EXPECT_EQ(service6.arr[8], 9); + EXPECT_EQ(service6.end, 6); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetOneLastServiceSingleton) +{ + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass3{}; }) + .addSingleton([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestMultiInheritClass2{}; }) + .addScoped([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestMultiInheritClass2{}; }) + .addScoped([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + const auto services = provider.getServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return TestMultiInheritClass2{}; }) + .addScoped([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldTryCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + const auto service3 = provider.tryCreateService(); + const auto service4 = provider.tryCreateService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + auto service3 = provider.createService(); + auto service4 = provider.createService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldNotCreateServiceInPlace) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldCreateServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = sb::di::ServiceCollection{} + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addSingleton([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .addScoped([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(options); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(MultiInheritanceFactoryTest, ShouldCreateServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addTransient([] { return TestMultiInheritClass2{}; }) + .addTransient([] { return TestMultiInheritClass3{}; }) + .addTransient([] { return TestMultiInheritClass4{}; }) + .buildServiceProvider(); + + const auto services = provider.createServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} diff --git a/Tests/Integration/MultiInheritanceUniqFactoryTest.cpp b/Tests/Integration/MultiInheritanceUniqFactoryTest.cpp new file mode 100644 index 0000000..c4dff2e --- /dev/null +++ b/Tests/Integration/MultiInheritanceUniqFactoryTest.cpp @@ -0,0 +1,339 @@ +#include +#include + +#include "../Helpers/Classes/MultiInherit.hpp" +#include "SevenBit/DI/ServiceCollection.hpp" + +class MultiInheritanceUniqFactoryTest : public testing::Test +{ + protected: + static void SetUpTestSuite() {} + + MultiInheritanceUniqFactoryTest() {} + + void SetUp() override {} + + void TearDown() override {} + + ~MultiInheritanceUniqFactoryTest() override = default; + + static void TearDownTestSuite() {} +}; + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldTryGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + auto service1 = provider.tryGetService(); + auto service2 = provider.tryGetService(); + auto service5 = provider.tryGetService(); + auto service6 = provider.tryGetService(); + + EXPECT_TRUE(service1); + EXPECT_TRUE(service2); + EXPECT_TRUE(service5); + EXPECT_TRUE(service6); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_FALSE(provider.tryGetService()); + EXPECT_EQ(service1->first(), 2); + EXPECT_EQ(service1->arr[0], 1); + EXPECT_EQ(service1->arr[8], 9); + EXPECT_EQ(service1->end, 1); + EXPECT_EQ(service2->second(), 22); + EXPECT_EQ(service2->arr[0], 1); + EXPECT_EQ(service2->arr[8], 9); + EXPECT_EQ(service2->end, 2); + EXPECT_EQ(service5->second(), 44); + EXPECT_EQ(service5->third(), 444); + EXPECT_EQ(service5->arr[0], 1); + EXPECT_EQ(service5->arr[8], 9); + EXPECT_EQ(service5->end, 5); + EXPECT_EQ(service6->fourth(), 4444); + EXPECT_EQ(service6->arr[0], 1); + EXPECT_EQ(service6->arr[8], 9); + EXPECT_EQ(service6->end, 6); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldTryGetOneLastServiceSingleton) +{ + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldTryGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto service = provider.tryGetService(); + + EXPECT_TRUE(service); + EXPECT_EQ(service->second(), 44); + EXPECT_EQ(service->arr[0], 1); + EXPECT_EQ(service->arr[8], 9); + EXPECT_EQ(service->end, 2); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + auto &service1 = provider.getService(); + auto &service2 = provider.getService(); + auto &service5 = provider.getService(); + auto &service6 = provider.getService(); + + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.getService(), sb::di::ServiceNotFoundException); + EXPECT_EQ(service1.first(), 2); + EXPECT_EQ(service1.arr[0], 1); + EXPECT_EQ(service1.arr[8], 9); + EXPECT_EQ(service1.end, 1); + EXPECT_EQ(service2.second(), 22); + EXPECT_EQ(service2.arr[0], 1); + EXPECT_EQ(service2.arr[8], 9); + EXPECT_EQ(service2.end, 2); + EXPECT_EQ(service5.first(), 4); + EXPECT_EQ(service5.second(), 44); + EXPECT_EQ(service5.third(), 444); + EXPECT_EQ(service5.arr[0], 1); + EXPECT_EQ(service5.arr[8], 9); + EXPECT_EQ(service5.end, 5); + EXPECT_EQ(service6.fourth(), 4444); + EXPECT_EQ(service6.arr[0], 1); + EXPECT_EQ(service6.arr[8], 9); + EXPECT_EQ(service6.end, 6); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetOneLastServiceSingleton) +{ + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetOneLastServiceScoped) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + auto &service = provider.getService(); + + EXPECT_EQ(service.second(), 44); + EXPECT_EQ(service.arr[0], 1); + EXPECT_EQ(service.arr[8], 9); + EXPECT_EQ(service.end, 2); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_TRUE(provider.getServices().empty()); + EXPECT_EQ(provider.getServices().size(), 1); + EXPECT_EQ(provider.getServices().size(), 1); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetCastedServicesInOrder) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto services = provider.getServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldGetServicesInOrderAfterNormalGet) +{ + auto provider = sb::di::ServiceCollection{} + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(); + + EXPECT_TRUE(provider.tryGetService()); + const auto services = provider.getServices(); + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldTryCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + const auto service3 = provider.tryCreateService(); + const auto service4 = provider.tryCreateService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); + EXPECT_FALSE(provider.tryCreateService()); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldCreateService) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + auto service3 = provider.createService(); + auto service4 = provider.createService(); + + EXPECT_TRUE(service3); + EXPECT_TRUE(service4); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createService(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldNotCreateServiceInPlace) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); + EXPECT_THROW(provider.createServiceInPlace(), sb::di::ServiceNotFoundException); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldCreateServices) +{ + sb::di::ServiceProviderOptions options; + options.checkServiceGlobalUniqueness = false; + auto provider = + sb::di::ServiceCollection{} + .addSingleton([] { return std::make_unique(); }) + .addSingleton([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .addScoped([] { return std::make_unique(); }) + .buildServiceProvider(options); + + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_EQ(provider.createServices().size(), 1); + EXPECT_TRUE(provider.createServices().empty()); + EXPECT_TRUE(provider.createServices().empty()); +} + +TEST_F(MultiInheritanceUniqFactoryTest, ShouldCreateServicesInOrder) +{ + auto provider = + sb::di::ServiceCollection{} + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .addTransient([] { return std::make_unique(); }) + .buildServiceProvider(); + + const auto services = provider.createServices(); + + EXPECT_EQ(services.size(), 3); + EXPECT_EQ(services[0]->second(), 22); + EXPECT_EQ(services[1]->second(), 33); + EXPECT_EQ(services[2]->second(), 44); +} From 49c42a57513afb35de78d39f4db0e98b19a01af9 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 6 Feb 2024 18:57:39 +0100 Subject: [PATCH 41/45] add ete tests --- Examples/CMakeLists.txt | 12 +++--- Tests/CMakeLists.txt | 1 + Tests/EndToEnd/CMakeLists.txt | 7 +++ Tests/EndToEnd/expectedTestData.json | 13 ++++++ Tests/EndToEnd/test_examples.py | 64 ++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 Tests/EndToEnd/CMakeLists.txt create mode 100644 Tests/EndToEnd/expectedTestData.json create mode 100644 Tests/EndToEnd/test_examples.py diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 7a0af92..b3d419e 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,14 +1,14 @@ file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp) -foreach(SOURCE ${SOURCES}) +foreach (SOURCE ${SOURCES}) get_filename_component(FILE_NAME ${SOURCE} NAME_WLE) - add_executable(${FILE_NAME} - ${SOURCE} + add_executable("${FILE_NAME}Example" + ${SOURCE} ) - target_link_libraries(${FILE_NAME} - 7bitDI + target_link_libraries("${FILE_NAME}Example" + 7bitDI ) -endforeach() \ No newline at end of file +endforeach () diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 6ec27b6..935023c 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -9,5 +9,6 @@ FetchContent_MakeAvailable(googletest) enable_testing() +add_subdirectory(EndToEnd) add_subdirectory(Integration) add_subdirectory(Unit) diff --git a/Tests/EndToEnd/CMakeLists.txt b/Tests/EndToEnd/CMakeLists.txt new file mode 100644 index 0000000..a93cd65 --- /dev/null +++ b/Tests/EndToEnd/CMakeLists.txt @@ -0,0 +1,7 @@ + +if (_7BIT_DI_BUILD_EXAMPLES) + find_package(Python REQUIRED) + + add_test(NAME EndToEnd.Examples COMMAND ${Python_EXECUTABLE} test_examples.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endif () diff --git a/Tests/EndToEnd/expectedTestData.json b/Tests/EndToEnd/expectedTestData.json new file mode 100644 index 0000000..0a16d64 --- /dev/null +++ b/Tests/EndToEnd/expectedTestData.json @@ -0,0 +1,13 @@ +{ + "Cli": "", + "CoreClasses": "", + "ExternalSingleton": "^Hello from service!", + "FactoryFunctions": "^Hello from service!", + "InjectingMultipleServices": "^work all: work A done! work B done! work C done! \nsingle work: work C done!", + "InjectingServiceProvider": "^actionA, actionB executed.", + "InjectingServices": "^actionA, actionB executed.", + "InjectionRules": "", + "SeparateImplementation": "^Hello from service.", + "ServicesLifeTime": ".*Singletons comparison.*", + "Simple": "^part a done!\npart b done!\n" +} diff --git a/Tests/EndToEnd/test_examples.py b/Tests/EndToEnd/test_examples.py new file mode 100644 index 0000000..355a1b0 --- /dev/null +++ b/Tests/EndToEnd/test_examples.py @@ -0,0 +1,64 @@ +import sys +import os +import subprocess +import re +import json + + +def getBinDir(): + if len(sys.argv) != 2: + raise Exception("binary directory not provided") + return sys.argv[1] + + +class ExamplesTest: + def __init__(self, binDir): + self.binDir = binDir + self.examplesPaths = self.__getAvailableExamples() + self.expectedTestMap = self.__getExpectedTestMap() + + def __getAvailableExamples(self): + paths = [os.path.join(self.binDir, f) for f in os.listdir(self.binDir) if "Example" in f] + return [f for f in paths if os.path.isfile(f)] + + def __getExpectedTestMap(self): + with open('expectedTestData.json') as data: + return json.load(data) + + def __runTest(self, examplePath, expected): + if expected is None: + raise Exception(f"example was not expected") + result = subprocess.run([examplePath], capture_output=True, text=True) + if result.returncode: + raise Exception(f"example returned non zero code {result.returncode}") + if not re.search(expected, result.stdout): + raise Exception(f"result of running example: '{result.stdout}' does not match expected: '{expected}'") + + def __runTestAndSummarize(self, examplePath): + name = os.path.basename(examplePath).split('.')[-1].replace("Example", "") + try: + self.__runTest(examplePath, self.expectedTestMap.get(name)) + print(f"{name} example test succeeded") + return True + except Exception as e: + print(f"{name} example test failed: {e}") + finally: + del self.expectedTestMap[name] + return False + + def run(self): + allTests = len(self.examplesPaths) + succeededTests = 0 + for count, examplePath in enumerate(self.examplesPaths, start=1): + print(f"Test {count}/{allTests}") + succeededTests += self.__runTestAndSummarize(examplePath) + if len(self.expectedTestMap): + raise Exception(f"Some expected tests were not run: {self.expectedTestMap.keys()}") + if succeededTests == allTests: + print(f"All test succeeded: {succeededTests}/{allTests}") + else: + raise Exception(f"Some tests failed: {allTests - succeededTests}/{allTests}") + + +if __name__ == "__main__": + ExamplesTest(getBinDir()).run() From 49113b5754bb74285ba59dcf4d0f5a1c9d7d1bcf Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 6 Feb 2024 19:26:44 +0100 Subject: [PATCH 42/45] fix ete on windows --- Tests/EndToEnd/test_examples.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Tests/EndToEnd/test_examples.py b/Tests/EndToEnd/test_examples.py index 355a1b0..53248b5 100644 --- a/Tests/EndToEnd/test_examples.py +++ b/Tests/EndToEnd/test_examples.py @@ -7,8 +7,12 @@ def getBinDir(): if len(sys.argv) != 2: + return "C:\\Users\\Sylwek\\Desktop\\7bitDI\\cmake-build-debug\\bin" raise Exception("binary directory not provided") - return sys.argv[1] + binDir = sys.argv[1] + if not os.path.exists(binDir): + raise Exception("Binary directory does not exist") + return binDir class ExamplesTest: @@ -18,7 +22,8 @@ def __init__(self, binDir): self.expectedTestMap = self.__getExpectedTestMap() def __getAvailableExamples(self): - paths = [os.path.join(self.binDir, f) for f in os.listdir(self.binDir) if "Example" in f] + paths = [os.path.join(self.binDir, f) for f in os.listdir(self.binDir) if + "Example" in f and os.path.splitext(f)[1] in [".exe", ""]] return [f for f in paths if os.path.isfile(f)] def __getExpectedTestMap(self): @@ -35,7 +40,8 @@ def __runTest(self, examplePath, expected): raise Exception(f"result of running example: '{result.stdout}' does not match expected: '{expected}'") def __runTestAndSummarize(self, examplePath): - name = os.path.basename(examplePath).split('.')[-1].replace("Example", "") + fileName = os.path.basename(examplePath) + name = os.path.splitext(fileName)[0].replace("Example", "") try: self.__runTest(examplePath, self.expectedTestMap.get(name)) print(f"{name} example test succeeded") From 2869667f54121e95697668557d5c008d3d23a29d Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Tue, 6 Feb 2024 19:31:16 +0100 Subject: [PATCH 43/45] remove test path --- Tests/EndToEnd/test_examples.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/EndToEnd/test_examples.py b/Tests/EndToEnd/test_examples.py index 53248b5..5e664dc 100644 --- a/Tests/EndToEnd/test_examples.py +++ b/Tests/EndToEnd/test_examples.py @@ -7,7 +7,6 @@ def getBinDir(): if len(sys.argv) != 2: - return "C:\\Users\\Sylwek\\Desktop\\7bitDI\\cmake-build-debug\\bin" raise Exception("binary directory not provided") binDir = sys.argv[1] if not os.path.exists(binDir): From 0bf713c88a5cd6f7ac3ea9aafb5283e2032009ab Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 7 Feb 2024 17:58:45 +0100 Subject: [PATCH 44/45] update documentation --- Docs/advanced-guides.rst | 6 +- Docs/advanced-guides/building-library.rst | 42 +--------- Docs/advanced-guides/using-aliases.rst | 15 ++++ Docs/advanced-guides/using-factories.rst | 5 +- .../injecting-multiple-services.rst | 2 +- Docs/basic-guides/injecting-services.rst | 2 +- Docs/basic-guides/injection-rules.rst | 8 +- Docs/basic-guides/services-lifetime.rst | 7 +- Docs/getting-started.rst | 4 +- Docs/reference/di.rst | 2 + Docs/reference/di/details/core.rst | 3 + .../core/iserviceinstanceproviderroot.rst | 6 ++ .../details/core/serviceinstancecreator.rst | 6 ++ .../details/core/serviceinstancesresolver.rst | 6 ++ Docs/reference/di/details/services.rst | 1 + .../di/details/services/aliasservice.rst | 6 ++ Docs/reference/di/details/utils.rst | 7 +- Docs/reference/di/details/utils/cast.rst | 6 ++ Docs/reference/di/details/utils/checkbase.rst | 6 ++ Docs/reference/di/details/utils/container.rst | 6 ++ .../di/details/utils/removeuniqueptr.rst | 10 +++ .../di/details/utils/requirebase.rst | 6 ++ Docs/reference/di/serviceinstance.rst | 6 ++ Docs/reference/di/servicelifetimes.rst | 6 ++ Examples/Guides/CoreClasses.cpp | 1 + Examples/Guides/InjectingServices.cpp | 1 + Examples/Guides/InjectionRules.cpp | 12 ++- Examples/Guides/ServiceAliases.cpp | 65 +++++++++++++++ .../SevenBit/DI/Details/Utils/CheckBase.hpp | 2 +- Include/SevenBit/DI/IServiceInstance.hpp | 2 +- .../SevenBit/DI/IServiceInstanceProvider.hpp | 4 +- Include/SevenBit/DI/ServiceCollection.hpp | 40 ++++++++-- Include/SevenBit/DI/ServiceDescriber.hpp | 34 ++++++-- Include/SevenBit/DI/ServiceDescriptor.hpp | 15 +++- Include/SevenBit/DI/ServiceInstance.hpp | 62 ++++++++++++-- Include/SevenBit/DI/ServiceProvider.hpp | 14 +++- .../SevenBit/DI/ServiceProviderOptions.hpp | 1 + Include/SevenBit/DI/TypeId.hpp | 3 + README.md | 80 +++++++++---------- Tests/EndToEnd/CMakeLists.txt | 2 +- Tests/EndToEnd/Examples/expectedTestData.json | 14 ++++ .../EndToEnd/{ => Examples}/test_examples.py | 0 Tests/EndToEnd/expectedTestData.json | 13 --- Tests/Helpers/Classes/Inherit.hpp | 2 + Tests/Integration/BasicUniqFactoryTest.cpp | 1 + 45 files changed, 396 insertions(+), 146 deletions(-) create mode 100644 Docs/advanced-guides/using-aliases.rst create mode 100644 Docs/reference/di/details/core/iserviceinstanceproviderroot.rst create mode 100644 Docs/reference/di/details/core/serviceinstancecreator.rst create mode 100644 Docs/reference/di/details/core/serviceinstancesresolver.rst create mode 100644 Docs/reference/di/details/services/aliasservice.rst create mode 100644 Docs/reference/di/details/utils/cast.rst create mode 100644 Docs/reference/di/details/utils/checkbase.rst create mode 100644 Docs/reference/di/details/utils/container.rst create mode 100644 Docs/reference/di/details/utils/removeuniqueptr.rst create mode 100644 Docs/reference/di/details/utils/requirebase.rst create mode 100644 Docs/reference/di/serviceinstance.rst create mode 100644 Docs/reference/di/servicelifetimes.rst create mode 100644 Examples/Guides/ServiceAliases.cpp create mode 100644 Tests/EndToEnd/Examples/expectedTestData.json rename Tests/EndToEnd/{ => Examples}/test_examples.py (100%) delete mode 100644 Tests/EndToEnd/expectedTestData.json diff --git a/Docs/advanced-guides.rst b/Docs/advanced-guides.rst index 8213136..a98ae92 100644 --- a/Docs/advanced-guides.rst +++ b/Docs/advanced-guides.rst @@ -6,10 +6,6 @@ Advanced Guides :titlesonly: advanced-guides/using-factories + advanced-guides/using-aliases advanced-guides/external-singleton advanced-guides/building-library - - - - - diff --git a/Docs/advanced-guides/building-library.rst b/Docs/advanced-guides/building-library.rst index b36fb66..2348493 100644 --- a/Docs/advanced-guides/building-library.rst +++ b/Docs/advanced-guides/building-library.rst @@ -20,8 +20,9 @@ Using this command several cache variables can be set: * : [possible values] (default value) - Description * _7BIT_DI_LIBRARY_TYPE: ["Shared", "Static", "HeaderOnly"] ("Static") - Library build type * _7BIT_DI_BUILD_DOCS: ["ON", "OFF"] ("OFF") - Turn on to build documentation (requires Sphinx_, Breathe_ and Doxygen_ to be installed) -* _7BIT_DI_BUILD_TESTS: ["ON", "OFF"] ("OFF") - Turn on to build tests (requires Gtest_ to be installed, see `Build Library With Conan`_) +* _7BIT_DI_BUILD_TESTS: ["ON", "OFF"] ("OFF") - Turn on to build tests * _7BIT_DI_BUILD_EXAMPLES: ["ON", "OFF"] ("OFF") - Turn on to build examples +* _7BIT_DI_BUILD_BENCHMARKS: ["ON", "OFF"] ("OFF") - Turn on to build benchmarks * _7BIT_DI_BUILD_SINGLE_HEADER: ["ON", "OFF"] ("OFF") - Turn on to build single header SevenBitDI.hpp (requires Quom_ to be installed) * _7BIT_DI_INSTALL: ["ON", "OFF"] ("OFF") - Turn on to install the library @@ -39,45 +40,10 @@ Build the library using the command: cmake --build . -Build Library With Conan -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Gtest_ library is added to project using Conan_ package manager (`Conan Installation`_), -If Conan was freshly installed run detect command: - -.. code-block:: sh - - conan profile detect - -To install Conan packages run this command in the library root folder: - -.. code-block:: sh - - conan install . --output-folder=build --build=missing - -Navigate to the build directory: - -.. code-block:: sh - - cd build - -Configure the CMake project, and add also toolchain file as a CMAKE_TOOLCHAIN_FILE cache variable: - -.. code-block:: sh - - cmake .. -DCMAKE_TOOLCHAIN_FILE:PATH="./conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -D_7BIT_DI_BUILD_TESTS=ON - -Build the library using the command: - -.. code-block:: sh - - cmake --build . - - Install Library ^^^^^^^^^^^^^^^^^^^^^^^^^ -To install the library set additional cache variables _7BIT_DI_BUILD_TESTS=ON and specify installation dir with CMAKE_INSTALL_PREFIX, then run the command +To install the library set additional cache variables _7BIT_DI_INSTALL=ON and specify installation dir with CMAKE_INSTALL_PREFIX, then run the command .. code-block:: sh @@ -91,4 +57,4 @@ To install the library set additional cache variables _7BIT_DI_BUILD_TESTS=ON an .. _Gtest: https://google.github.io/googletest/ .. _Conan: https://conan.io/ .. _Quom: https://pypi.org/project/quom/ -.. _`Conan Installation`: https://conan.io/downloads.html \ No newline at end of file +.. _`Conan Installation`: https://conan.io/downloads.html diff --git a/Docs/advanced-guides/using-aliases.rst b/Docs/advanced-guides/using-aliases.rst new file mode 100644 index 0000000..fe2f284 --- /dev/null +++ b/Docs/advanced-guides/using-aliases.rst @@ -0,0 +1,15 @@ +Using Aliases +======================================== + +With the use of aliases, one service can be injected through its multiple base classes, also aliases can be chained. +If multiple aliases are registered with the same base class only last will be used. + + +.. literalinclude:: ../../Examples/Guides/ServiceAliases.cpp + :caption: Examples/Guides/ServiceAliases + :language: C++ + +.. code-block:: console + :caption: Output + + actionA from top service, actionB from top service executed. diff --git a/Docs/advanced-guides/using-factories.rst b/Docs/advanced-guides/using-factories.rst index 63d9a55..7c04746 100644 --- a/Docs/advanced-guides/using-factories.rst +++ b/Docs/advanced-guides/using-factories.rst @@ -2,9 +2,10 @@ Using Factories ======================================== Factory functor can be provided to manually create a service. -Functor should return unique_ptr or T if object is movable/copyable and should optionally take other services as arguments. +Functor should return unique_ptr or raw object if the type is movable/copyable and should optionally take other services as arguments. + Functor scheme (Services...) -> std::unique_ptr< T> | T -Where Services are pointers, in place objects (if object is movable or copyable), unique pointers, references, vectors with pointers or unique pointers +Where Services are pointers, in-place objects (if an object is movable or copyable), unique pointers, references, vectors with pointers or unique pointers .. literalinclude:: ../../Examples/Guides/FactoryFunctions.cpp :caption: Examples/Guides/FactoryFunctions diff --git a/Docs/basic-guides/injecting-multiple-services.rst b/Docs/basic-guides/injecting-multiple-services.rst index 1b30d35..5e10799 100644 --- a/Docs/basic-guides/injecting-multiple-services.rst +++ b/Docs/basic-guides/injecting-multiple-services.rst @@ -5,7 +5,7 @@ Multiple services can inherit one interface and can be injected using a vector. .. Note:: Service objects are ordered in vectors using registration order. - The last registered service of base type is used when resolving one service + The last registered service with the same base type is used when resolving one service Injection rules are simple: diff --git a/Docs/basic-guides/injecting-services.rst b/Docs/basic-guides/injecting-services.rst index fb4cebf..7e96272 100644 --- a/Docs/basic-guides/injecting-services.rst +++ b/Docs/basic-guides/injecting-services.rst @@ -8,7 +8,7 @@ This example shows the main purpose of this library, injecting services into ser * Service should have one constructor * Singleton/scoped service should be injected using pointers or references - * Transient services should be injected using std::unique_ptr + * Transient services should be injected using std::unique_ptr or directly by type if an object is movable or copyable .. literalinclude:: ../../Examples/Guides/InjectingServices.cpp :caption: Examples/Guides/InjectingServices diff --git a/Docs/basic-guides/injection-rules.rst b/Docs/basic-guides/injection-rules.rst index 5d0b9c4..5ea7c97 100644 --- a/Docs/basic-guides/injection-rules.rst +++ b/Docs/basic-guides/injection-rules.rst @@ -14,15 +14,11 @@ Injecting Services --------------------- * Singleton/scoped services can be injected using one of: * References: (T&) - * Const references: (const T&) * Pointers: (T*) - * Const pointer: (T* const) - * Pointer to const object: (const T*) - * Const pointer to const object: (const T* const) * Transient services can be injected using one of: * std::unique_ptr: (unique_ptr) - * In place object if type is movable or copyable: T -* Multiple services implementing specified interface can be injected using std::vector: + * In-place object if type is movable or copyable: T +* Multiple services implementing the same interface can be injected using std::vector: * Transient (std::vector>) * Singleton/scoped (std::vector) diff --git a/Docs/basic-guides/services-lifetime.rst b/Docs/basic-guides/services-lifetime.rst index c94de65..5f19a2e 100644 --- a/Docs/basic-guides/services-lifetime.rst +++ b/Docs/basic-guides/services-lifetime.rst @@ -9,14 +9,17 @@ Service providers can create scoped service providers: ServiceProvider scoped = provider.createScope() +.. warning:: + Root/main service provider cannot be destroyed before its children scoped providers this can lead to undefined behavior + Service can be registered as a singleton, scoped, or transient. * Singleton: service provider will create only one instance of this service (accessible via the getService method) * Scoped: instance provider will create only one instance of this instance for each scope (accessible via the getService method) -* Transient: services are always unique, a new service is provided every time it is requested, and the service provider returns, in this case, std::unique_ptr (accessible via createService method) +* Transient: services are always unique, a new service is provided every time it is requested (accessible via createService or createInstanceInPlace method) .. warning:: - Only transient services can be created using createInstance method otherwise the method will throw an exception + Only transient services can be created using createInstance/createInstanceInPlace method otherwise the method will throw an exception Only singleton/scoped services can be accessed using the getService method otherwise the method will throw an exception diff --git a/Docs/getting-started.rst b/Docs/getting-started.rst index ef4166b..911e3c4 100644 --- a/Docs/getting-started.rst +++ b/Docs/getting-started.rst @@ -48,7 +48,7 @@ Installation .. code-block:: Txt [requires] - 7bitdi/2.0.0 + 7bitdi/2.1.0 change the version to newer if available, then run the command: @@ -56,7 +56,7 @@ Installation conan install . --output-folder=build --build=missing - Follow in detail instructions available at `Conan Tutorial`_ + Follow in detailed instructions available at `Conan Tutorial`_ #. Header only Download source code from the most recent release, diff --git a/Docs/reference/di.rst b/Docs/reference/di.rst index 9c8e1f8..4e68300 100644 --- a/Docs/reference/di.rst +++ b/Docs/reference/di.rst @@ -13,7 +13,9 @@ sb::di di/servicecollection di/servicedescriber di/servicedescriptor + di/serviceinstance di/servicelifetime + di/servicelifetimes di/serviceprovider di/serviceprovideroptions di/typeid diff --git a/Docs/reference/di/details/core.rst b/Docs/reference/di/details/core.rst index fb3bc4d..c1b3917 100644 --- a/Docs/reference/di/details/core.rst +++ b/Docs/reference/di/details/core.rst @@ -5,5 +5,8 @@ sb::di::details::core :maxdepth: 5 :titlesonly: + core/iserviceinstanceproviderroot.rst + core/serviceinstancecreator.rst core/serviceinstanceprovider.rst core/serviceinstanceproviderroot.rst + core/serviceinstancesresolver.rst diff --git a/Docs/reference/di/details/core/iserviceinstanceproviderroot.rst b/Docs/reference/di/details/core/iserviceinstanceproviderroot.rst new file mode 100644 index 0000000..605cb7c --- /dev/null +++ b/Docs/reference/di/details/core/iserviceinstanceproviderroot.rst @@ -0,0 +1,6 @@ +IServiceInstanceProviderRoot +======================================== + +.. doxygenstruct:: sb::di::details::core::IServiceInstanceProviderRoot + :members: + :undoc-members: diff --git a/Docs/reference/di/details/core/serviceinstancecreator.rst b/Docs/reference/di/details/core/serviceinstancecreator.rst new file mode 100644 index 0000000..c7f1e5e --- /dev/null +++ b/Docs/reference/di/details/core/serviceinstancecreator.rst @@ -0,0 +1,6 @@ +ServiceInstanceCreator +======================================== + +.. doxygenclass:: sb::di::details::core::ServiceInstanceCreator + :members: + :undoc-members: diff --git a/Docs/reference/di/details/core/serviceinstancesresolver.rst b/Docs/reference/di/details/core/serviceinstancesresolver.rst new file mode 100644 index 0000000..6ba02ec --- /dev/null +++ b/Docs/reference/di/details/core/serviceinstancesresolver.rst @@ -0,0 +1,6 @@ +ServiceInstancesResolver +======================================== + +.. doxygenclass:: sb::di::details::core::ServiceInstancesResolver + :members: + :undoc-members: diff --git a/Docs/reference/di/details/services.rst b/Docs/reference/di/details/services.rst index b0a0f70..80f35f6 100644 --- a/Docs/reference/di/details/services.rst +++ b/Docs/reference/di/details/services.rst @@ -5,6 +5,7 @@ sb::di::details::services :maxdepth: 5 :titlesonly: + services/aliasservice.rst services/externalservice.rst services/inplaceservice.rst services/uniqueptrservice.rst diff --git a/Docs/reference/di/details/services/aliasservice.rst b/Docs/reference/di/details/services/aliasservice.rst new file mode 100644 index 0000000..e2764cf --- /dev/null +++ b/Docs/reference/di/details/services/aliasservice.rst @@ -0,0 +1,6 @@ +AliasService +======================================== + +.. doxygenclass:: sb::di::details::services::AliasService + :members: + :undoc-members: diff --git a/Docs/reference/di/details/utils.rst b/Docs/reference/di/details/utils.rst index c3ac476..0efda87 100644 --- a/Docs/reference/di/details/utils.rst +++ b/Docs/reference/di/details/utils.rst @@ -6,9 +6,14 @@ sb::di::details::utils :titlesonly: utils/assert.rst + utils/cast.rst utils/check.rst - utils/require.rst + utils/checkbase.rst + utils/container.rst utils/ctorparamsnumber.rst utils/iscopyctor.rst utils/isinplaceobject.rst utils/isuniqueptr.rst + utils/removeuniqueptr.rst + utils/require.rst + utils/requirebase.rst diff --git a/Docs/reference/di/details/utils/cast.rst b/Docs/reference/di/details/utils/cast.rst new file mode 100644 index 0000000..56630b4 --- /dev/null +++ b/Docs/reference/di/details/utils/cast.rst @@ -0,0 +1,6 @@ +Cast +======================================== + +.. doxygenstruct:: sb::di::details::utils::Cast + :members: + :undoc-members: diff --git a/Docs/reference/di/details/utils/checkbase.rst b/Docs/reference/di/details/utils/checkbase.rst new file mode 100644 index 0000000..badbc04 --- /dev/null +++ b/Docs/reference/di/details/utils/checkbase.rst @@ -0,0 +1,6 @@ +CheckBase +======================================== + +.. doxygenstruct:: sb::di::details::utils::CheckBase + :members: + :undoc-members: diff --git a/Docs/reference/di/details/utils/container.rst b/Docs/reference/di/details/utils/container.rst new file mode 100644 index 0000000..72a4aa2 --- /dev/null +++ b/Docs/reference/di/details/utils/container.rst @@ -0,0 +1,6 @@ +Container +======================================== + +.. doxygenstruct:: sb::di::details::utils::Container + :members: + :undoc-members: diff --git a/Docs/reference/di/details/utils/removeuniqueptr.rst b/Docs/reference/di/details/utils/removeuniqueptr.rst new file mode 100644 index 0000000..026b920 --- /dev/null +++ b/Docs/reference/di/details/utils/removeuniqueptr.rst @@ -0,0 +1,10 @@ +RemoveUniquePtr +======================================== + +.. doxygenstruct:: sb::di::details::utils::RemoveUniquePtr + :members: + :undoc-members: + +.. doxygenstruct:: sb::di::details::utils::RemoveUniquePtr< std::unique_ptr< T > > + :members: + :undoc-members: diff --git a/Docs/reference/di/details/utils/requirebase.rst b/Docs/reference/di/details/utils/requirebase.rst new file mode 100644 index 0000000..e29dc6d --- /dev/null +++ b/Docs/reference/di/details/utils/requirebase.rst @@ -0,0 +1,6 @@ +RequireBase +======================================== + +.. doxygenstruct:: sb::di::details::utils::RequireBase + :members: + :undoc-members: diff --git a/Docs/reference/di/serviceinstance.rst b/Docs/reference/di/serviceinstance.rst new file mode 100644 index 0000000..c60f879 --- /dev/null +++ b/Docs/reference/di/serviceinstance.rst @@ -0,0 +1,6 @@ +ServiceInstance +======================================== + +.. doxygenclass:: sb::di::ServiceInstance + :members: + :undoc-members: diff --git a/Docs/reference/di/servicelifetimes.rst b/Docs/reference/di/servicelifetimes.rst new file mode 100644 index 0000000..1d5ed20 --- /dev/null +++ b/Docs/reference/di/servicelifetimes.rst @@ -0,0 +1,6 @@ +ServiceLifeTimes +======================================== + +.. doxygenstruct:: sb::di::ServiceLifeTimes + :members: + :undoc-members: diff --git a/Examples/Guides/CoreClasses.cpp b/Examples/Guides/CoreClasses.cpp index b9051be..4c6d6e9 100644 --- a/Examples/Guides/CoreClasses.cpp +++ b/Examples/Guides/CoreClasses.cpp @@ -11,6 +11,7 @@ struct ServiceB struct ServiceC { }; + int main() { // Service registration diff --git a/Examples/Guides/InjectingServices.cpp b/Examples/Guides/InjectingServices.cpp index 889af79..0a1c1ed 100644 --- a/Examples/Guides/InjectingServices.cpp +++ b/Examples/Guides/InjectingServices.cpp @@ -43,6 +43,7 @@ class ServiceExecutor return _serviceA.actionA() + ", " + _serviceB->actionB() + " executed."; } }; + int main() { ServiceProvider provider = ServiceCollection{} diff --git a/Examples/Guides/InjectionRules.cpp b/Examples/Guides/InjectionRules.cpp index 8d11473..e939ca4 100644 --- a/Examples/Guides/InjectionRules.cpp +++ b/Examples/Guides/InjectionRules.cpp @@ -20,12 +20,16 @@ struct TransientService class ServiceExecutor { public: - ServiceExecutor(NotReqisteredService *notRegistered, const SingletonService &singleton, - const std::vector scoped, std::vector> trasients) + ServiceExecutor(NotReqisteredService *notRegistered, SingletonService &singleton, ScopedService *scoped, + std::unique_ptr transient, TransientService transientInPlace, + std::vector scopedList, + std::vector> trasientList) { assert(notRegistered == nullptr); - assert(scoped.size() == 1); - assert(trasients.size() == 1); + assert(scoped != nullptr); + assert(transient != nullptr); + assert(scopedList.size() == 1); + assert(trasientList.size() == 1); } }; int main() diff --git a/Examples/Guides/ServiceAliases.cpp b/Examples/Guides/ServiceAliases.cpp new file mode 100644 index 0000000..dffff32 --- /dev/null +++ b/Examples/Guides/ServiceAliases.cpp @@ -0,0 +1,65 @@ +#include +#include + +using namespace sb::di; + +struct IServiceA +{ + virtual std::string actionA() = 0; + + virtual ~IServiceA() = default; +}; + +struct IServiceB +{ + virtual std::string actionB() = 0; + + virtual ~IServiceB() = default; +}; + +struct ServiceA : IServiceA +{ + std::string actionA() override { return "actionA"; } +}; + +struct ServiceB : IServiceB +{ + std::string actionB() override { return "actionB"; } +}; + +struct Service final : ServiceA, ServiceB +{ + std::string actionA() override { return "actionA from top service"; } + std::string actionB() override { return "actionB from top service"; } +}; + +class ServiceExecutor +{ + IServiceA &_serviceA; + IServiceB &_serviceB; + + public: + ServiceExecutor(IServiceA &serviceA, IServiceB &serviceB) : _serviceA(serviceA), _serviceB(serviceB) {} + + [[nodiscard]] std::string execute() const + { + return _serviceA.actionA() + ", " + _serviceB.actionB() + " executed."; + } +}; + +int main() +{ + ServiceProvider provider = ServiceCollection{} + .addSingleton() + .addAlias() + .addAlias() + .addAlias() + .addAlias() + .addScoped() + .buildServiceProvider(); + + const auto &executor = provider.getService(); + + std::cout << executor.execute(); + return 0; +} diff --git a/Include/SevenBit/DI/Details/Utils/CheckBase.hpp b/Include/SevenBit/DI/Details/Utils/CheckBase.hpp index eb7d162..e5215fd 100644 --- a/Include/SevenBit/DI/Details/Utils/CheckBase.hpp +++ b/Include/SevenBit/DI/Details/Utils/CheckBase.hpp @@ -7,7 +7,7 @@ namespace sb::di::details::utils { - struct EXPORT CheckBase + struct CheckBase { template constexpr static bool notNull(const std::unique_ptr &ptr) { return notNull(ptr.get()); } diff --git a/Include/SevenBit/DI/IServiceInstance.hpp b/Include/SevenBit/DI/IServiceInstance.hpp index a3d8019..eb70e84 100644 --- a/Include/SevenBit/DI/IServiceInstance.hpp +++ b/Include/SevenBit/DI/IServiceInstance.hpp @@ -60,7 +60,7 @@ namespace sb::di /** * @brief Checks if service instance is valid - * @details If service instance is invalid, get and move methods might lead to undefined behaviour + * @details If service instance is invalid, get and release methods might lead to undefined behaviour */ [[nodiscard]] virtual bool isValid() const = 0; diff --git a/Include/SevenBit/DI/IServiceInstanceProvider.hpp b/Include/SevenBit/DI/IServiceInstanceProvider.hpp index c889bfc..4981f8c 100644 --- a/Include/SevenBit/DI/IServiceInstanceProvider.hpp +++ b/Include/SevenBit/DI/IServiceInstanceProvider.hpp @@ -62,7 +62,7 @@ namespace sb::di /** * @brief Creates service instance unique pointer, might be null - * @details If service was not registered or was registered as scoped/singleton, method returns null + * @details If service was not registered or was registered as scoped/singleton, method returns invalid instance */ virtual ServiceInstance tryCreateInstance(TypeId serviceTypeId) = 0; @@ -81,7 +81,7 @@ namespace sb::di /** * @brief Creates service instance in place - * @details If service was not registered or was registered as scoped/singleton, method returns null + * @details If service was not registered or was registered as scoped/singleton, method returns invalid instance */ virtual ServiceInstance tryCreateInstanceInPlace(TypeId serviceTypeId) = 0; diff --git a/Include/SevenBit/DI/ServiceCollection.hpp b/Include/SevenBit/DI/ServiceCollection.hpp index b8eb975..09a26c3 100644 --- a/Include/SevenBit/DI/ServiceCollection.hpp +++ b/Include/SevenBit/DI/ServiceCollection.hpp @@ -9,11 +9,8 @@ #include "SevenBit/DI/Details/Utils/Container.hpp" #include "SevenBit/DI/ServiceDescriber.hpp" -#include "SevenBit/DI/ServiceDescriptor.hpp" -#include "SevenBit/DI/ServiceLifeTime.hpp" +#include "SevenBit/DI/ServiceLifeTimes.hpp" #include "SevenBit/DI/ServiceProvider.hpp" -#include "SevenBit/DI/ServiceProviderOptions.hpp" -#include "SevenBit/DI/TypeId.hpp" namespace sb::di { @@ -243,6 +240,7 @@ namespace sb::di * @details Returns iterator following the last removed element */ Iterator remove(Iterator pos); + /** * @brief Removes descriptor with given iterator * @details Returns iterator following the last removed element @@ -254,6 +252,7 @@ namespace sb::di * @details Returns iterator following the last removed element */ Iterator removeRange(Iterator begin, Iterator end); + /** * @brief Removes descriptors between given iterators * @details Returns iterator following the last removed element @@ -333,8 +332,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTime::scoped()); - * ServiceCollection{}.add(ServiceLifeTime::transient()); + * ServiceCollection{}.add(ServiceLifeTimes::Scoped); + * ServiceCollection{}.add(ServiceLifeTimes::Transient); * @endcode */ template @@ -342,6 +341,7 @@ namespace sb::di { return add(ServiceDescriber::describe(lifeTime)); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -364,6 +364,7 @@ namespace sb::di { return add(ServiceDescriber::describeSingleton()); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -386,6 +387,7 @@ namespace sb::di { return add(ServiceDescriber::describeScoped()); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -428,6 +430,7 @@ namespace sb::di { return add(ServiceDescriber::describeSingleton(service)); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -464,7 +467,7 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTime::scoped(), + * ServiceCollection{}.add(ServiceLifeTimes::Scoped, * []() { return std::make_unique(); }); * @endcode */ @@ -473,6 +476,7 @@ namespace sb::di { return add(ServiceDescriber::describeFrom(lifeTime, std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -494,6 +498,7 @@ namespace sb::di { return add(ServiceDescriber::describeSingletonFrom(std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -515,6 +520,7 @@ namespace sb::di { return add(ServiceDescriber::describeScopedFrom(std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -550,13 +556,14 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceCollection{}.add(ServiceLifeTime::transient(), []() { return std::make_unique(); }); + * ServiceCollection{}.add(ServiceLifeTimes::Transient, []() { return std::make_unique(); }); * @endcode */ template ServiceCollection &add(const ServiceLifeTime lifeTime, FactoryFcn factory) { return add(ServiceDescriber::describeFrom(lifeTime, std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -577,6 +584,7 @@ namespace sb::di { return add(ServiceDescriber::describeSingletonFrom(std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -597,6 +605,7 @@ namespace sb::di { return add(ServiceDescriber::describeScopedFrom(std::move(factory))); } + /** * @brief Adds service descriptor * @details Adds service descriptor with: @@ -618,6 +627,21 @@ namespace sb::di return add(ServiceDescriber::describeTransientFrom(std::move(factory))); } + /** + * @brief Adds service descriptor + * @details Adds service descriptor with: + * lifetime - scoped, + * serviceTypeId - typeid(TAlias), + * implementationTypeId - typeid(TService), + * factory - nullptr + * @tparam TAlias base service type - alias type + * @tparam TService service type must inherit from TService + * + * Example: + * @code{.cpp} + * ServiceCollection{}.addAlias(); + * @endcode + */ template ServiceCollection &addAlias() { return add(ServiceDescriber::describeAlias()); diff --git a/Include/SevenBit/DI/ServiceDescriber.hpp b/Include/SevenBit/DI/ServiceDescriber.hpp index 8851143..1c22f8d 100644 --- a/Include/SevenBit/DI/ServiceDescriber.hpp +++ b/Include/SevenBit/DI/ServiceDescriber.hpp @@ -60,6 +60,7 @@ namespace sb::di { return describe(ServiceLifeTimes::Scoped); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -96,9 +97,9 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceDescriptor descriptor1 = ServiceDescriber::describe(ServiceLifeTime::scoped()); + * ServiceDescriptor descriptor1 = ServiceDescriber::describe(ServiceLifeTimes::Scoped); * ServiceDescriptor descriptor2 = - * ServiceDescriber::describe(ServiceLifeTime::transient()); + * ServiceDescriber::describe(ServiceLifeTimes::Transient); * @endcode */ template @@ -136,6 +137,7 @@ namespace sb::di { return describeSingleton(&service); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -205,11 +207,11 @@ namespace sb::di * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ - template static ServiceDescriptor describeScopedFrom(FactoryFcn &&factory) { return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -227,7 +229,6 @@ namespace sb::di * [](const ServiceDescriptor &) { return std::make_unique(); }); * @endcode */ - template static ServiceDescriptor describeTransientFrom(FactoryFcn &&factory) { return describeFrom(ServiceLifeTimes::Transient, std::forward(factory)); @@ -246,8 +247,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( - * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); + * ServiceDescriptor descriptor = ServiceDescriber::describeFrom(ServiceLifeTimes::Scoped, + * []() { return std::make_unique(); }); * @endcode */ template @@ -278,6 +279,7 @@ namespace sb::di { return describeFrom(ServiceLifeTimes::Singleton, std::forward(factory)); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -300,6 +302,7 @@ namespace sb::di { return describeFrom(ServiceLifeTimes::Scoped, std::forward(factory)); } + /** * @brief Creates service descriptor * @details Creates service descriptor with: @@ -337,8 +340,8 @@ namespace sb::di * * Example: * @code{.cpp} - * ServiceDescriptor descriptor = ServiceDescriber::describeFrom( - * []() { return std::make_unique(); }, ServiceLifeTime::scoped()); + * ServiceDescriptor descriptor = ServiceDescriber::describeFrom(ServiceLifeTimes::Scoped, + * []() { return std::make_unique(); }); * @endcode */ template @@ -354,6 +357,21 @@ namespace sb::di details::utils::Cast::getCastOffset()}; } + /** + * @brief Creates service descriptor + * @details Creates service descriptor with: + * lifetime - scoped, + * serviceTypeId - typeid(TAlias), + * implementationTypeId - typeid(TService), + * factory - nullptr + * @tparam TAlias base service type - alias type + * @tparam TService service type must inherit from TService + * + * Example: + * @code{.cpp} + * ServiceDescriptor descriptor = ServiceDescriber::describeAlias(); + * @endcode + */ template static ServiceDescriptor describeAlias() { details::utils::Assert::aliasNotSame(); diff --git a/Include/SevenBit/DI/ServiceDescriptor.hpp b/Include/SevenBit/DI/ServiceDescriptor.hpp index b322c8e..dac4aa1 100644 --- a/Include/SevenBit/DI/ServiceDescriptor.hpp +++ b/Include/SevenBit/DI/ServiceDescriptor.hpp @@ -21,8 +21,13 @@ namespace sb::di /** * @brief Construct a new service descriptor object - * @details implementationFactory cannot be null, otherwise constructor will throw exception - * @throws sb::di::NullPointerException + * @param serviceTypeId - service type identifier + * @param implementationTypeId - service implementation type identifier, type must inhetit from service type + * @param lifeTime - service life time: Singleton, Scoped or Transient + * @param implementationFactory - service implementation factory, can be nullptr in that case describer is + * treated as alias + * @param castOffset - cast offset is a difference in bytes between implementation pointer and casted service + * pointer, should be non zero for multiinheritance scenarios */ ServiceDescriptor(TypeId serviceTypeId, TypeId implementationTypeId, ServiceLifeTime lifeTime, IServiceFactory::Ptr implementationFactory, ptrdiff_t castOffset = 0); @@ -53,10 +58,14 @@ namespace sb::di */ [[nodiscard]] const IServiceFactory &getImplementationFactory() const; + /** + * @brief Get the service cast offset, non zero for multiinheritance + * @details + */ [[nodiscard]] ptrdiff_t getCastOffset() const; /** - * @brief Check if service is alias + * @brief Check if service is alias (implementation factory is nullptr) */ [[nodiscard]] bool isAlias() const; diff --git a/Include/SevenBit/DI/ServiceInstance.hpp b/Include/SevenBit/DI/ServiceInstance.hpp index 8af5256..3106c0b 100644 --- a/Include/SevenBit/DI/ServiceInstance.hpp +++ b/Include/SevenBit/DI/ServiceInstance.hpp @@ -16,8 +16,14 @@ namespace sb::di public: using Ptr = std::unique_ptr; + /** + * @brief Creates default invalid service instance + */ ServiceInstance() = default; + /** + * @brief Created service instance with specified implementation and cast offset + */ explicit ServiceInstance(IServiceInstance::Ptr implementation, ptrdiff_t castOffset = 0); ServiceInstance(const ServiceInstance &other) = delete; @@ -26,18 +32,47 @@ namespace sb::di ServiceInstance &operator=(const ServiceInstance &other) = delete; ServiceInstance &operator=(ServiceInstance &&other) = default; + /** + * @brief Try get service instance implementation + */ IServiceInstance *tryGetImplementation(); + + /** + * @brief Try get service instance implementation + */ [[nodiscard]] const IServiceInstance *tryGetImplementation() const; + /** + * @brief Get service instance implementation + * @details If service instance implementation is nullptr, method throws exception + * @throws sb::di::NullPointerException + */ IServiceInstance &getImplementation(); + + /** + * @brief Get service instance implementation + * @details If service instance implementation is nullptr, method throws exception + * @throws sb::di::NullPointerException + */ [[nodiscard]] const IServiceInstance &getImplementation() const; + /** + * @details cast offset is added to service pointer when get/release methods are used + */ void addCastOffset(ptrdiff_t castOffset); + + /** + * @details cast offset is added to service pointer when get/release methods are used + */ void setCastOffset(ptrdiff_t castOffset); + + /** + * @details cast offset is added to service pointer when get/release methods are used + */ [[nodiscard]] ptrdiff_t getCastOffset() const; /** - * @brief Checks if service instance is valid + * @brief Checks if service instance is valid (implementation is not nullptr and implementation is valid) * @details If service instance is invalid, get and move methods might lead to undefined behaviour */ [[nodiscard]] bool isValid() const; @@ -53,7 +88,7 @@ namespace sb::di * * Example: * @code{.cpp} - * T* service = instance->getAs(); + * T* service = instance.getAs(); * @endcode */ template [[nodiscard]] T *getAs() const @@ -64,10 +99,12 @@ namespace sb::di /** * @brief Releases service ownership as pointer T * * @details The client is responsible for ensuring that the T type is correct + * @warning Using this method might cause memory leaks, client is responsible for managing this pointner + * lifetime, the best approach is to immediately wrap this pointer with proper std::unique_ptr * * Example: * @code{.cpp} - * T* service = instance->releaseAs(); + * T* service = instance.releaseAs(); * @endcode */ template T *releaseAs() { return static_cast(applyOffset(getImplementation().release())); } @@ -78,7 +115,7 @@ namespace sb::di * * Example: * @code{.cpp} - * std::unique_ptr service = instance->moveOutAsUniquePtr(); + * std::unique_ptr service = instance.moveOutAsUniquePtr(); * @endcode */ template std::unique_ptr moveOutAsUniquePtr() { return std::unique_ptr{releaseAs()}; } @@ -89,7 +126,7 @@ namespace sb::di * * Example: * @code{.cpp} - * T service = instance->moveOutAs(); + * T service = instance.moveOutAs(); * @endcode */ template T &&moveOutAs() @@ -97,6 +134,21 @@ namespace sb::di return std::move(*static_cast(applyOffset(getImplementation().getForMoveOut()))); } + /** + * @brief Copies service as T + * @details The client is responsible for ensuring that the T type is correct + * + * Example: + * @code{.cpp} + * T service = instance.copyAs(); + * @endcode + */ + template T copyAs() { return *static_cast(applyOffset(getImplementation().getForMoveOut())); } + + /** + * @brief Clears service instance (implemnentation is reset) + * @details after clearing instance becomes invalid + */ void clear(); private: diff --git a/Include/SevenBit/DI/ServiceProvider.hpp b/Include/SevenBit/DI/ServiceProvider.hpp index 73c8f0b..a52a7df 100644 --- a/Include/SevenBit/DI/ServiceProvider.hpp +++ b/Include/SevenBit/DI/ServiceProvider.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "SevenBit/DI/LibraryConfig.hpp" @@ -8,6 +9,7 @@ #include "SevenBit/DI/Details/Utils/Check.hpp" #include "SevenBit/DI/Details/Utils/Require.hpp" #include "SevenBit/DI/IServiceInstanceProvider.hpp" +#include "SevenBit/DI/ServiceProviderOptions.hpp" namespace sb::di { @@ -68,14 +70,17 @@ namespace sb::di * @endcode */ [[nodiscard]] Ptr createScopeAsPtr() const; + /** * @brief Returns inner service instance provider + * @details If service instance provider is nullptr, method throws exception * @throws sb::di::NullPointerException */ [[nodiscard]] const IServiceInstanceProvider &getInstanceProvider() const; /** * @brief Returns inner service instance provider + * @details If service instance provider is nullptr, method throws exception * @throws sb::di::NullPointerException */ IServiceInstanceProvider &getInstanceProvider(); @@ -202,7 +207,14 @@ namespace sb::di { auto instance = getInstanceProvider().createInstanceInPlace(typeid(TService)); details::utils::Require::validInstance(instance); - return instance.moveOutAs(); + if constexpr (std::is_move_constructible_v) + { + return instance.moveOutAs(); + } + else + { + return instance.copyAs(); + } } /** diff --git a/Include/SevenBit/DI/ServiceProviderOptions.hpp b/Include/SevenBit/DI/ServiceProviderOptions.hpp index b2fb2e7..e4455bf 100644 --- a/Include/SevenBit/DI/ServiceProviderOptions.hpp +++ b/Include/SevenBit/DI/ServiceProviderOptions.hpp @@ -14,6 +14,7 @@ namespace sb::di * @details If set to true service provider will destruct services in opposite order to construction. */ bool strongDestructionOrder = false; + /** * @brief Set prebuilds singletons * @details If set to true when service provider is constructed it will also construct all singletons diff --git a/Include/SevenBit/DI/TypeId.hpp b/Include/SevenBit/DI/TypeId.hpp index 2005aef..5fa7a9f 100644 --- a/Include/SevenBit/DI/TypeId.hpp +++ b/Include/SevenBit/DI/TypeId.hpp @@ -11,6 +11,9 @@ namespace sb::di */ using TypeId = std::type_index; + /** + * @brief Alias of std::type_info + */ using TypeInfo = std::type_info; } // namespace sb::di diff --git a/README.md b/README.md index 1c92cf4..c842f55 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Windows](https://github.com/7bitcoder/7bitDI/actions/workflows/Windows.yml/badge.svg)](https://github.com/7bitcoder/7bitDI/actions/workflows/Windows.yml) [![MacOs](https://github.com/7bitcoder/7bitDI/actions/workflows/MacOs.yml/badge.svg)](https://github.com/7bitcoder/7bitDI/actions/workflows/MacOs.yml) [![Conan Center](https://img.shields.io/conan/v/7bitdi)](https://conan.io/center/recipes/7bitdi) +
logo @@ -25,6 +26,10 @@ ## Built With - [Google Test](https://github.com/google/googletest) +- [Google Benchmark](https://github.com/google/benchmark) +- [Sphinx](https://www.sphinx-doc.org/en/master/) +- [Breathe](https://breathe.readthedocs.io/en/latest/) +- [Quom](https://pypi.org/project/quom/) ## Supported Platforms @@ -34,15 +39,15 @@ The library is officially supported on the following platforms: **Operating systems:** -* Linux -* macOS -* Windows +- Linux +- macOS +- Windows **Compilers:** -* gcc 7.0+ -* clang 6.0+ -* MSVC 2015+ +- gcc 7.0+ +- clang 6.0+ +- MSVC 2015+ If you notice any problems/bugs, please file an issue on the repository GitHub Issue Tracker. Pull requests containing fixes are welcome! @@ -53,7 +58,7 @@ fixes are welcome! ### 1. Using Cmake fetch content api - Recommended -Update CMakeLists.txt file with following code +Update CMakeLists.txt file with the following code ```cmake include(FetchContent) @@ -73,7 +78,7 @@ Download and install A [Conan](https://conan.io/), and create conanfile.txt in t ``` [requires] -7bitdi/2.0.0 +7bitdi/2.1.0 ``` change the version to newer if available, then run the command: @@ -82,15 +87,13 @@ change the version to newer if available, then run the command: conan install . --output-folder=build --build=missing ``` -Follow in detail instructions available +Follow in detailed instructions available at [Conan Tutorial](https://docs.conan.io/2/tutorial/consuming_packages/build_simple_cmake_project.html) ### 3. Header only -Download source code from the most recent release, +Download the source code from the most recent release, copy include folder into your project location. -For example copy into the '/SevenBitDI' folder. -Include this folder into the project, with [Cmake](https://cmake.org/), u can use: ```cmake include_directories(/SevenBitDI/Include) @@ -111,55 +114,50 @@ in [Documentation](https://7bitdi.readthedocs.io/en/latest/getting-started.html) ### The library relies on two core classes: -* ServiceCollection: class is responsible for registering services and building service provider -* ServiceProvider: class is responsible for delivering real services and managing its lifetime +- ServiceCollection: class is responsible for registering services and building service provider +- ServiceProvider: class is responsible for delivering real services and managing its lifetime -The dependency injection system relies heavily on template metaprogramming, and it has some limitations. +The dependency injection mechanism relies heavily on template metaprogramming and it has some limitations. ### General -* Only one constructor should be defined for each instance implementation -* If the service is registered with interface and implementation, the interface should have a virtual destructor -* If multiple services are registered by the same interface, all should have the same lifetime singleton, scoped or - transient (the build method will throw an exception) -* Only one service implementation can be registered (the build method will throw an exception) +- Only one constructor should be defined for each instance implementation +- If the service is registered with interface and implementation, the interface should have a virtual destructor +- If multiple services are registered by the same interface, all should have the same lifetime (the build method will + throw an exception) +- Only one service implementation can be registered (the build method will throw an exception) ### Service lifetime Service can be registered as a singleton, scoped, or transient. -* Singleton: service provider will create only one instance of this service (accessible via the getService - method) -* Scoped: instance provider will create only one instance of this instance for each scope (accessible via the getService +- Singleton: service provider will create only one instance of this service (accessible via the getService method) +- Scoped: instance provider will create only one instance of this instance for each scope (accessible via the getService method) -* Transient: services are always unique, a new service is provided every time it is requested, and the service provider - returns, in this case, std::unique_ptr (accessible via createService method) +- Transient: services are always unique, a new service is provided every time it is requested (accessible via + createService or createInstanceInPlace method) ### Injecting Services -* Singleton/scoped services can be injected using one of: - * References: (T&) - * Const references: (const T&) - * Pointers: (T*) - * Const pointer: (T* const) - * Pointer to const object: (const T*) - * Const pointer to const object: (const T* const) -* Transient services can be injected using one of: - * std::unique_ptr: (unique_ptr< T>) - * In place object if type is movable or copyable: T -* Multiple services implementing specified interface can be injected using std::vector: - * Transient (std::vector>) - * Singleton/scoped (std::vector) +- Singleton/scoped services can be injected using one of: + - References: (T&) + - Pointers: (T\*) +- Transient services can be injected using one of: + - std::unique_ptr: (unique_ptr< T>) + - In place object if the type is movable or copyable: T +- Multiple services implementing the same interface can be injected using std::vector: + - Transient (std::vector>) + - Singleton/scoped (std::vector) ### Injection Table | Constructor param type | ServiceProvider method used | -|----------------------------------|-------------------------------------| +| -------------------------------- | ----------------------------------- | | T - if movable or copyable | provider.createServiceInPlace< T>() | | std::unique_ptr< T> | provider.createService< T>() | | T& | provider.getService< T>() | -| T* | provider.tryGetService< T>() | -| std::vector | provider.getServices< T>() | +| T\* | provider.tryGetService< T>() | +| std::vector | provider.getServices< T>() | | std::vector> | provider.createServices< T>() | ### Sample Usage diff --git a/Tests/EndToEnd/CMakeLists.txt b/Tests/EndToEnd/CMakeLists.txt index a93cd65..e301759 100644 --- a/Tests/EndToEnd/CMakeLists.txt +++ b/Tests/EndToEnd/CMakeLists.txt @@ -3,5 +3,5 @@ if (_7BIT_DI_BUILD_EXAMPLES) find_package(Python REQUIRED) add_test(NAME EndToEnd.Examples COMMAND ${Python_EXECUTABLE} test_examples.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Examples) endif () diff --git a/Tests/EndToEnd/Examples/expectedTestData.json b/Tests/EndToEnd/Examples/expectedTestData.json new file mode 100644 index 0000000..aa32ea6 --- /dev/null +++ b/Tests/EndToEnd/Examples/expectedTestData.json @@ -0,0 +1,14 @@ +{ + "Cli": "", + "CoreClasses": "", + "ExternalSingleton": "^Hello from service!", + "FactoryFunctions": "^Hello from service!", + "InjectingMultipleServices": "^work all: work A done! work B done! work C done! \nsingle work: work C done!", + "InjectingServiceProvider": "^actionA, actionB executed.", + "InjectingServices": "^actionA, actionB executed.", + "InjectionRules": "", + "SeparateImplementation": "^Hello from service.", + "ServicesLifeTime": "\nSingletons comparison\nrootProvider\\s+== rootProvider:\\s+1\nrootProvider\\s+== scopedProvider:\\s+1\nscopedProvider\\s+== scopedProvider:\\s+1\n\nScoped comparison\nrootProvider\\s+== rootProvider:\\s+1\nrootProvider\\s+== scopedProvider:\\s+0\nscopedProvider\\s+== scopedProvider:\\s+1\n\nTransient comparison\nrootProvider\\s+== rootProvider:\\s+0\nrootProvider\\s+== scopedProvider:\\s+0\nscopedProvider\\s+== scopedProvider:\\s+0\n", + "Simple": "^part a done!\npart b done!\n", + "ServiceAliases": "actionA from top service, actionB from top service executed." +} diff --git a/Tests/EndToEnd/test_examples.py b/Tests/EndToEnd/Examples/test_examples.py similarity index 100% rename from Tests/EndToEnd/test_examples.py rename to Tests/EndToEnd/Examples/test_examples.py diff --git a/Tests/EndToEnd/expectedTestData.json b/Tests/EndToEnd/expectedTestData.json deleted file mode 100644 index 0a16d64..0000000 --- a/Tests/EndToEnd/expectedTestData.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Cli": "", - "CoreClasses": "", - "ExternalSingleton": "^Hello from service!", - "FactoryFunctions": "^Hello from service!", - "InjectingMultipleServices": "^work all: work A done! work B done! work C done! \nsingle work: work C done!", - "InjectingServiceProvider": "^actionA, actionB executed.", - "InjectingServices": "^actionA, actionB executed.", - "InjectionRules": "", - "SeparateImplementation": "^Hello from service.", - "ServicesLifeTime": ".*Singletons comparison.*", - "Simple": "^part a done!\npart b done!\n" -} diff --git a/Tests/Helpers/Classes/Inherit.hpp b/Tests/Helpers/Classes/Inherit.hpp index f6ca629..b0e0e93 100644 --- a/Tests/Helpers/Classes/Inherit.hpp +++ b/Tests/Helpers/Classes/Inherit.hpp @@ -3,6 +3,8 @@ struct TestInheritClass1 { virtual int number() { return 1; } + + virtual ~TestInheritClass1() = default; }; struct TestInheritClass2 : TestInheritClass1 { diff --git a/Tests/Integration/BasicUniqFactoryTest.cpp b/Tests/Integration/BasicUniqFactoryTest.cpp index 3849872..8172678 100644 --- a/Tests/Integration/BasicUniqFactoryTest.cpp +++ b/Tests/Integration/BasicUniqFactoryTest.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "../Helpers/Classes/Basic.hpp" #include "../Helpers/Classes/CirularDependency.hpp" From 412d38cf5ad4f828b7fa5d0230bae45c4f143249 Mon Sep 17 00:00:00 2001 From: 7bitcoder Date: Wed, 7 Feb 2024 18:18:06 +0100 Subject: [PATCH 45/45] update cmake txt format --- Benchmarks/CMakeLists.txt | 16 +++---- CMakeLists.txt | 59 ++++++++++++------------- Cmake/Setup.cmake | 74 ++++++++++++++++---------------- Docs/CMakeLists.txt | 26 +++++------ Examples/CMakeLists.txt | 18 ++++---- SingleHeader/CMakeLists.txt | 16 +++---- Source/CMakeLists.txt | 13 +++--- Tests/CMakeLists.txt | 6 +-- Tests/EndToEnd/CMakeLists.txt | 6 +-- Tests/Integration/CMakeLists.txt | 10 ++--- Tests/Unit/CMakeLists.txt | 10 ++--- 11 files changed, 127 insertions(+), 127 deletions(-) diff --git a/Benchmarks/CMakeLists.txt b/Benchmarks/CMakeLists.txt index f75c30b..72a393f 100644 --- a/Benchmarks/CMakeLists.txt +++ b/Benchmarks/CMakeLists.txt @@ -1,8 +1,8 @@ include(FetchContent) FetchContent_Declare( - benchmark - GIT_REPOSITORY https://github.com/google/benchmark.git - GIT_TAG 344117638c8ff7e239044fd0fa7085839fc03021 # release-1.14.0 + benchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG 344117638c8ff7e239044fd0fa7085839fc03021 # release-1.14.0 ) FetchContent_MakeAvailable(benchmark) @@ -10,15 +10,15 @@ enable_testing() file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp) -foreach (SOURCE ${SOURCES}) +foreach(SOURCE ${SOURCES}) get_filename_component(FILE_NAME ${SOURCE} NAME_WLE) add_executable(${FILE_NAME} - ${SOURCE} + ${SOURCE} ) target_link_libraries(${FILE_NAME} - 7bitDI - benchmark::benchmark + 7bitDI + benchmark::benchmark ) -endforeach () +endforeach() diff --git a/CMakeLists.txt b/CMakeLists.txt index baa7473..f95fdd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,9 +12,10 @@ project(${_7BIT_DI_LIBRARY} LANGUAGES CXX VERSION ${_7BIT_DI_VERSION}) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Cmake") -if (NOT CMAKE_CXX_STANDARD) +if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) -endif () +endif() + set(CMAKE_CXX_STANDARD_REQUIRED ON) include(Setup) @@ -25,27 +26,27 @@ include_directories(${_7BIT_DI_INCLUDE_DIR}) add_subdirectory(Source) -if (_7BIT_DI_BUILD_DOCS) +if(_7BIT_DI_BUILD_DOCS) add_subdirectory(Docs) -endif () +endif() -if (_7BIT_DI_BUILD_TESTS) +if(_7BIT_DI_BUILD_TESTS) add_subdirectory(Tests) -endif () +endif() -if (_7BIT_DI_BUILD_EXAMPLES) +if(_7BIT_DI_BUILD_EXAMPLES) add_subdirectory(Examples) -endif () +endif() -if (_7BIT_DI_BUILD_BENCHMARKS) +if(_7BIT_DI_BUILD_BENCHMARKS) add_subdirectory(Benchmarks) -endif () +endif() -if (_7BIT_DI_BUILD_SINGLE_HEADER) +if(_7BIT_DI_BUILD_SINGLE_HEADER) add_subdirectory(SingleHeader) -endif () +endif() -if (_7BIT_DI_INSTALL) +if(_7BIT_DI_INSTALL) set(PROJECT_CONFIG_IN ${CMAKE_CURRENT_SOURCE_DIR}/Cmake/7bitDIConfig.cmake.in) set(PROJECT_CONFIG_OUT ${CMAKE_CURRENT_BINARY_DIR}/7bitDIConfig.cmake) set(CONFIG_TARGETS_FILE 7bitDIConfigTargets.cmake) @@ -55,29 +56,29 @@ if (_7BIT_DI_INSTALL) install(DIRECTORY ${_7BIT_DI_INCLUDE_DIR}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( - TARGETS 7bitDI - EXPORT 7bitDI - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + TARGETS 7bitDI + EXPORT 7bitDI + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) export( - TARGETS 7bitDI - NAMESPACE 7bitDI:: - FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) + TARGETS 7bitDI + NAMESPACE 7bitDI:: + FILE ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_TARGETS_FILE}) install( - EXPORT 7bitDI - EXPORT 7bitDI - DESTINATION ${EXPORT_DEST_DIR} - NAMESPACE 7bitDI:: - NAMESPACE 7bitDI:: - FILE ${CONFIG_TARGETS_FILE}) + EXPORT 7bitDI + EXPORT 7bitDI + DESTINATION ${EXPORT_DEST_DIR} + NAMESPACE 7bitDI:: + NAMESPACE 7bitDI:: + FILE ${CONFIG_TARGETS_FILE}) include(CMakePackageConfigHelpers) configure_package_config_file(${PROJECT_CONFIG_IN} ${PROJECT_CONFIG_OUT} - INSTALL_DESTINATION ${EXPORT_DEST_DIR}) + INSTALL_DESTINATION ${EXPORT_DEST_DIR}) write_basic_package_version_file(${VERSIONS_CONFIG_FILE} COMPATIBILITY SameMajorVersion) @@ -86,4 +87,4 @@ if (_7BIT_DI_INSTALL) export(PACKAGE 7bitDI) include(CPack) -endif () +endif() diff --git a/Cmake/Setup.cmake b/Cmake/Setup.cmake index a7a9df1..83959ad 100644 --- a/Cmake/Setup.cmake +++ b/Cmake/Setup.cmake @@ -1,8 +1,8 @@ include(Functions) -if (NOT CMAKE_BUILD_TYPE) +if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE) -endif () +endif() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin) @@ -33,20 +33,20 @@ set(_7BIT_DI_DETAILS_DIR "${_7BIT_DI_DI_DIR}/Details") set(_7BIT_DI_MAIN_HEADER "${_7BIT_DI_INCLUDE_DIR}/SevenBit/DI.hpp") file(GLOB _7BIT_DI_TOP_HEADERS "${_7BIT_DI_DI_DIR}/*.hpp") file(GLOB _7BIT_DI_DETAILS_HEADERS - "${_7BIT_DI_DETAILS_DIR}/Containers/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Core/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Factories/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Helpers/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Services/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Utils/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Containers/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Core/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Factories/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Helpers/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Services/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Utils/*.hpp" ) file(GLOB _7BIT_DI_IMPL_HEADERS - "${_7BIT_DI_DI_DIR}/Impl/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Containers/Impl/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Core/Impl/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Factories/Impl/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Helpers/Impl/*.hpp" - "${_7BIT_DI_DETAILS_DIR}/Utils/Impl/*.hpp" + "${_7BIT_DI_DI_DIR}/Impl/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Containers/Impl/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Core/Impl/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Factories/Impl/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Helpers/Impl/*.hpp" + "${_7BIT_DI_DETAILS_DIR}/Utils/Impl/*.hpp" ) set(_7BIT_DI_ALL_HEADERS ${_7BIT_DI_MAIN_HEADER} ${_7BIT_DI_TOP_HEADERS} ${_7BIT_DI_DETAILS_HEADERS} ${_7BIT_DI_IMPL_HEADERS}) @@ -63,20 +63,20 @@ option(_7BIT_DI_BUILD_DOCS "Turn on to build documentation (requires sphinx and option(_7BIT_DI_INSTALL "Installs 7bitDI" OFF) option(_7BIT_DI_BUILD_SINGLE_HEADER "Builds single header SevenBitDI.hpp" OFF) -if (_7BIT_DI_BUILD_PIC) +if(_7BIT_DI_BUILD_PIC) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -endif () +endif() -if (_7BIT_DI_LIBRARY_TYPE STREQUAL "Shared" OR BUILD_SHARED_LIBS) +if(_7BIT_DI_LIBRARY_TYPE STREQUAL "Shared" OR BUILD_SHARED_LIBS) set(_7BIT_DI_BUILD_LIBRARY_TYPE "Shared") set(_7BIT_DI_SHARED_LIB ON) -elseif (_7BIT_DI_LIBRARY_TYPE STREQUAL "HeaderOnly") +elseif(_7BIT_DI_LIBRARY_TYPE STREQUAL "HeaderOnly") set(_7BIT_DI_BUILD_LIBRARY_TYPE "HeaderOnly") set(_7BIT_DI_HEADER_ONLY_LIB ON) -else () +else() set(_7BIT_DI_BUILD_LIBRARY_TYPE "Static") set(_7BIT_DI_STATIC_LIB ON) -endif () +endif() configure_file(${_7BIT_DI_DI_DIR}/CmakeDef.hpp.input ${_7BIT_DI_DI_DIR}/CmakeDef.hpp) @@ -84,22 +84,22 @@ set(BYTE_SIZE 8) math(EXPR MEMORY_SIZE "${CMAKE_SIZEOF_VOID_P} * ${BYTE_SIZE}") set(INFOS - "${_7BIT_DI_LIBRARY} ${_7BIT_DI_VERSION}" - "Build type: ${CMAKE_BUILD_TYPE}" - "Library type: ${_7BIT_DI_BUILD_LIBRARY_TYPE}" - "==================================================" - "Cmake version: ${CMAKE_VERSION}" - "Os: ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION}" - "Architecture: ${CMAKE_SYSTEM_PROCESSOR} ${MEMORY_SIZE}bit" - "CXX compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}" - "CXX standard: ${CMAKE_CXX_STANDARD}" - "Generator: ${CMAKE_GENERATOR}" - "==================================================" - "Build tests: ${_7BIT_DI_BUILD_TESTS}" - "Build examples: ${_7BIT_DI_BUILD_EXAMPLES}" - "Build benchmarks: ${_7BIT_DI_BUILD_BENCHMARKS}" - "Build documentation: ${_7BIT_DI_BUILD_DOCS}" - "Build single header: ${_7BIT_DI_BUILD_SINGLE_HEADER}" - "Install project: ${_7BIT_DI_INSTALL}" + "${_7BIT_DI_LIBRARY} ${_7BIT_DI_VERSION}" + "Build type: ${CMAKE_BUILD_TYPE}" + "Library type: ${_7BIT_DI_BUILD_LIBRARY_TYPE}" + "==================================================" + "Cmake version: ${CMAKE_VERSION}" + "Os: ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION}" + "Architecture: ${CMAKE_SYSTEM_PROCESSOR} ${MEMORY_SIZE}bit" + "CXX compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}" + "CXX standard: ${CMAKE_CXX_STANDARD}" + "Generator: ${CMAKE_GENERATOR}" + "==================================================" + "Build tests: ${_7BIT_DI_BUILD_TESTS}" + "Build examples: ${_7BIT_DI_BUILD_EXAMPLES}" + "Build benchmarks: ${_7BIT_DI_BUILD_BENCHMARKS}" + "Build documentation: ${_7BIT_DI_BUILD_DOCS}" + "Build single header: ${_7BIT_DI_BUILD_SINGLE_HEADER}" + "Install project: ${_7BIT_DI_INSTALL}" ) printInfo("${INFOS}" = 50 7 0) diff --git a/Docs/CMakeLists.txt b/Docs/CMakeLists.txt index bec6f41..db3d529 100644 --- a/Docs/CMakeLists.txt +++ b/Docs/CMakeLists.txt @@ -12,19 +12,19 @@ set(SPHINX_OUT ${SPHINX_SOURCE}/conf.py) configure_file(${SPHINX_IN} ${SPHINX_OUT} @ONLY) add_custom_command(OUTPUT ${SPHINX_INDEX_FILE} - COMMAND - ${SPHINX_EXECUTABLE} -b html - ${SPHINX_SOURCE} ${SPHINX_BUILD} - WORKING_DIRECTORY ${SPHINX_SOURCE} - DEPENDS - ${SPHINX_RST_FILES} - ${EXAMPLES} - ${SOURCES} - MAIN_DEPENDENCY ${SPHINX_OUT} - COMMENT "Generating documentation with Sphinx") + COMMAND + ${SPHINX_EXECUTABLE} -b html + ${SPHINX_SOURCE} ${SPHINX_BUILD} + WORKING_DIRECTORY ${SPHINX_SOURCE} + DEPENDS + ${SPHINX_RST_FILES} + ${EXAMPLES} + ${SOURCES} + MAIN_DEPENDENCY ${SPHINX_OUT} + COMMENT "Generating documentation with Sphinx") add_custom_target(GenerateDoc - ALL DEPENDS - ${SPHINX_INDEX_FILE} - ${SPHINX_RST_FILES} + ALL DEPENDS + ${SPHINX_INDEX_FILE} + ${SPHINX_RST_FILES} ) diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index b3d419e..b13785e 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -1,14 +1,14 @@ file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp) -foreach (SOURCE ${SOURCES}) - get_filename_component(FILE_NAME ${SOURCE} NAME_WLE) +foreach(SOURCE ${SOURCES}) + get_filename_component(FILE_NAME ${SOURCE} NAME_WLE) - add_executable("${FILE_NAME}Example" - ${SOURCE} - ) + add_executable("${FILE_NAME}Example" + ${SOURCE} + ) - target_link_libraries("${FILE_NAME}Example" - 7bitDI - ) -endforeach () + target_link_libraries("${FILE_NAME}Example" + 7bitDI + ) +endforeach() diff --git a/SingleHeader/CMakeLists.txt b/SingleHeader/CMakeLists.txt index bce7429..28930f3 100644 --- a/SingleHeader/CMakeLists.txt +++ b/SingleHeader/CMakeLists.txt @@ -4,14 +4,14 @@ set(_7BIT_DI_SINGLE_IN ${CMAKE_CURRENT_SOURCE_DIR}/SevenBitDI.hpp.in) set(_7BIT_DI_SINGLE_OUT ${CMAKE_CURRENT_BINARY_DIR}/SevenBitDI.hpp) add_custom_command(OUTPUT ${_7BIT_DI_SINGLE_OUT} - COMMAND - ${QUOM_EXECUTABLE} ${_7BIT_DI_SINGLE_IN} ${_7BIT_DI_SINGLE_OUT} -I ${_7BIT_DI_INCLUDE_DIR} - DEPENDS - ${_7BIT_DI_ALL_HEADERS} - COMMENT "Generating single header with Quom") + COMMAND + ${QUOM_EXECUTABLE} ${_7BIT_DI_SINGLE_IN} ${_7BIT_DI_SINGLE_OUT} -I ${_7BIT_DI_INCLUDE_DIR} + DEPENDS + ${_7BIT_DI_ALL_HEADERS} + COMMENT "Generating single header with Quom") add_custom_target(GenerateSingleHeader - ALL DEPENDS - ${_7BIT_DI_SINGLE_OUT} - ${_7BIT_DI_MAIN_HEADER} + ALL DEPENDS + ${_7BIT_DI_SINGLE_OUT} + ${_7BIT_DI_MAIN_HEADER} ) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 63468d0..017f34d 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1,16 +1,15 @@ include(GenerateExportHeader) -if (_7BIT_DI_SHARED_LIB) +if(_7BIT_DI_SHARED_LIB) add_library(7bitDI SHARED Source.cpp) -elseif (_7BIT_DI_STATIC_LIB) +elseif(_7BIT_DI_STATIC_LIB) add_library(7bitDI STATIC Source.cpp) -elseif (_7BIT_DI_HEADER_ONLY_LIB) +elseif(_7BIT_DI_HEADER_ONLY_LIB) add_library(7bitDI INTERFACE) - -endif () +endif() add_library(7bitDI::7bitDI ALIAS 7bitDI) @@ -19,5 +18,5 @@ set_target_properties(7bitDI PROPERTIES DEBUG_POSTFIX d) string(REPLACE ";" "$" dirs "${_7BIT_DI_INCLUDE_DIR}") target_include_directories(7bitDI SYSTEM INTERFACE - "$" - "$/${CMAKE_INSTALL_INCLUDEDIR}>") + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 935023c..77d16b2 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,8 +1,8 @@ include(FetchContent) FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # release-1.14.0 + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG f8d7d77c06936315286eb55f8de22cd23c188571 # release-1.14.0 ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) diff --git a/Tests/EndToEnd/CMakeLists.txt b/Tests/EndToEnd/CMakeLists.txt index e301759..e31b832 100644 --- a/Tests/EndToEnd/CMakeLists.txt +++ b/Tests/EndToEnd/CMakeLists.txt @@ -1,7 +1,7 @@ -if (_7BIT_DI_BUILD_EXAMPLES) +if(_7BIT_DI_BUILD_EXAMPLES) find_package(Python REQUIRED) add_test(NAME EndToEnd.Examples COMMAND ${Python_EXECUTABLE} test_examples.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Examples) -endif () + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Examples) +endif() diff --git a/Tests/Integration/CMakeLists.txt b/Tests/Integration/CMakeLists.txt index f6ac48a..42f8b37 100644 --- a/Tests/Integration/CMakeLists.txt +++ b/Tests/Integration/CMakeLists.txt @@ -1,15 +1,15 @@ file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp) add_executable(IntegrationTests - ${SOURCES} + ${SOURCES} ) target_link_libraries(IntegrationTests PUBLIC - GTest::gtest - GTest::gmock - 7bitDI + GTest::gtest + GTest::gmock + 7bitDI ) include(GoogleTest) gtest_discover_tests(IntegrationTests - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/Tests/Unit/CMakeLists.txt b/Tests/Unit/CMakeLists.txt index 4dffae9..3f133cf 100644 --- a/Tests/Unit/CMakeLists.txt +++ b/Tests/Unit/CMakeLists.txt @@ -1,15 +1,15 @@ file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS *.cpp) add_executable(UnitTests - ${SOURCES} + ${SOURCES} ) target_link_libraries(UnitTests PUBLIC - GTest::gtest - GTest::gmock - 7bitDI + GTest::gtest + GTest::gmock + 7bitDI ) include(GoogleTest) gtest_discover_tests(UnitTests - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})