From 5864e5abc43b201c3801fa39a2fcaf9e3a9e8914 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 27 Feb 2022 12:54:10 +0100 Subject: refactor: use dependency injection --- src/DI/auto_wirable.hpp | 28 +++++++++++++++++++ src/DI/auto_wirable.tpp | 10 +++++++ src/DI/container.hpp | 65 +++++++++++++++++++++++++++++++++++++++++++ src/DI/container.tpp | 53 +++++++++++++++++++++++++++++++++++ src/DI/function_wrapper.hpp | 20 +++++++++++++ src/DI/function_wrapper.tpp | 9 ++++++ src/DI/interfaces/wrapper.hpp | 17 +++++++++++ src/DI/object_type.cpp | 18 ++++++++++++ src/DI/object_type.hpp | 35 +++++++++++++++++++++++ src/DI/object_wrapper.hpp | 20 +++++++++++++ src/DI/object_wrapper.tpp | 9 ++++++ 11 files changed, 284 insertions(+) create mode 100644 src/DI/auto_wirable.hpp create mode 100644 src/DI/auto_wirable.tpp create mode 100644 src/DI/container.hpp create mode 100644 src/DI/container.tpp create mode 100644 src/DI/function_wrapper.hpp create mode 100644 src/DI/function_wrapper.tpp create mode 100644 src/DI/interfaces/wrapper.hpp create mode 100644 src/DI/object_type.cpp create mode 100644 src/DI/object_type.hpp create mode 100644 src/DI/object_wrapper.hpp create mode 100644 src/DI/object_wrapper.tpp (limited to 'src/DI') diff --git a/src/DI/auto_wirable.hpp b/src/DI/auto_wirable.hpp new file mode 100644 index 0000000..13d252e --- /dev/null +++ b/src/DI/auto_wirable.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "DI/container.hpp" + +#include + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class IGenericAutoWirable +{ +public: + virtual ~IGenericAutoWirable() = default; +}; + +template +class IAutoWirable : public IGenericAutoWirable +{ +public: + static Interface resolve(); +}; + +template +class AutoWirable : public IAutoWirable +{ +public: + static std::shared_ptr resolve(const Container &container); +}; + +#include "auto_wirable.tpp" diff --git a/src/DI/auto_wirable.tpp b/src/DI/auto_wirable.tpp new file mode 100644 index 0000000..6c0d111 --- /dev/null +++ b/src/DI/auto_wirable.tpp @@ -0,0 +1,10 @@ +#pragma once + +#include "auto_wirable.hpp" + +template +std::shared_ptr +AutoWirable::resolve(const Container &container) +{ + return std::make_shared(container.get()...); +} diff --git a/src/DI/container.hpp b/src/DI/container.hpp new file mode 100644 index 0000000..2402894 --- /dev/null +++ b/src/DI/container.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "DI/object_type.hpp" +#include "interfaces/wrapper.hpp" + +#include +#include +#include +#include + +class Container; + +template +class BindingBuilder +{ +public: + explicit BindingBuilder(Container *container); + + template >> + void to(); + + void to_factory(Interface func); + +private: + Container *_container; +}; + +template +struct is_func : public std::false_type // NOLINT(readability-identifier-naming) +{ +}; + +template +struct is_func> : public std::true_type +{ +}; + +class Container +{ +public: + Container() = default; + + template + BindingBuilder bind(); + + template >> + std::shared_ptr get() const; + + /* + template && + std::is_invocable_v>> + Interface get() const; + */ + + template ::value>> + Interface get() const; + + std::unordered_map, ObjectTypeHasher> + bindings; +}; + +#include "container.tpp" diff --git a/src/DI/container.tpp b/src/DI/container.tpp new file mode 100644 index 0000000..21bf81a --- /dev/null +++ b/src/DI/container.tpp @@ -0,0 +1,53 @@ +#pragma once + +#include "container.hpp" + +#include "function_wrapper.hpp" +#include "object_wrapper.hpp" + +template +BindingBuilder::BindingBuilder(Container *container) : _container(container) +{ +} + +template +template +void BindingBuilder::to() +{ + _container->bindings.emplace( + ObjectType(), + std::dynamic_pointer_cast( + std::make_shared>(*_container))); +} + +template +void BindingBuilder::to_factory(Interface func) +{ + _container->bindings.emplace(ObjectType(), + std::dynamic_pointer_cast( + std::make_shared>(func))); +} + +template +BindingBuilder Container::bind() +{ + return BindingBuilder(this); +} + +template +std::shared_ptr Container::get() const +{ + auto wrapper = std::dynamic_pointer_cast>>( + bindings.at(ObjectType())); + + return wrapper->get(); +} + +template +Interface Container::get() const +{ + auto wrapper = std::dynamic_pointer_cast>( + bindings.at(ObjectType())); + + return wrapper->get(); +} diff --git a/src/DI/function_wrapper.hpp b/src/DI/function_wrapper.hpp new file mode 100644 index 0000000..e4b6779 --- /dev/null +++ b/src/DI/function_wrapper.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "DI/container.hpp" +#include "DI/interfaces/wrapper.hpp" + +#include + +template +class FunctionWrapper : public IWrapper +{ +public: + explicit FunctionWrapper(Interface func) : _func(func) {} + + [[nodiscard]] Interface get() const; + +private: + const Interface _func; +}; + +#include "function_wrapper.tpp" diff --git a/src/DI/function_wrapper.tpp b/src/DI/function_wrapper.tpp new file mode 100644 index 0000000..4e09957 --- /dev/null +++ b/src/DI/function_wrapper.tpp @@ -0,0 +1,9 @@ +#pragma once + +#include "function_wrapper.hpp" + +template +Interface FunctionWrapper::get() const +{ + return _func; +} diff --git a/src/DI/interfaces/wrapper.hpp b/src/DI/interfaces/wrapper.hpp new file mode 100644 index 0000000..3cc75a0 --- /dev/null +++ b/src/DI/interfaces/wrapper.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class IGenericWrapper +{ +public: + virtual ~IGenericWrapper() = default; +}; + +template +class IWrapper : public IGenericWrapper +{ +public: + [[nodiscard]] virtual Interface get() const = 0; +}; diff --git a/src/DI/object_type.cpp b/src/DI/object_type.cpp new file mode 100644 index 0000000..60c7c78 --- /dev/null +++ b/src/DI/object_type.cpp @@ -0,0 +1,18 @@ +#include "object_type.hpp" + +BaseObjectType::BaseObjectType(const std::type_info &type_info) : _type_info(type_info) {} + +bool BaseObjectType::operator==(const BaseObjectType &object_type) const +{ + return hash() == object_type.hash(); +} + +std::size_t BaseObjectType::hash() const +{ + return _type_info.hash_code(); +} + +std::size_t ObjectTypeHasher::operator()(const BaseObjectType &object_type) const +{ + return object_type.hash(); +} diff --git a/src/DI/object_type.hpp b/src/DI/object_type.hpp new file mode 100644 index 0000000..f690a64 --- /dev/null +++ b/src/DI/object_type.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +class BaseObjectType +{ +public: + explicit BaseObjectType(const std::type_info &type_info); + + bool operator==(const BaseObjectType &object_type) const; + + [[nodiscard]] std::size_t hash() const; + +private: + const std::type_info &_type_info; +}; + +template +class ObjectType : public BaseObjectType +{ +public: + ObjectType() : BaseObjectType(typeid(Object)) {} +}; + +class IObjectTypeHasher +{ +public: + virtual std::size_t operator()(const BaseObjectType &object_type) const = 0; +}; + +class ObjectTypeHasher : public IObjectTypeHasher +{ +public: + std::size_t operator()(const BaseObjectType &object_type) const override; +}; diff --git a/src/DI/object_wrapper.hpp b/src/DI/object_wrapper.hpp new file mode 100644 index 0000000..0ae66df --- /dev/null +++ b/src/DI/object_wrapper.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "DI/container.hpp" +#include "DI/interfaces/wrapper.hpp" + +#include + +template +class ObjectWrapper : public IWrapper> +{ +public: + explicit ObjectWrapper(const Container &container) : _container(container) {} + + [[nodiscard]] std::shared_ptr get() const; + +private: + const Container &_container; +}; + +#include "object_wrapper.tpp" diff --git a/src/DI/object_wrapper.tpp b/src/DI/object_wrapper.tpp new file mode 100644 index 0000000..7efefc4 --- /dev/null +++ b/src/DI/object_wrapper.tpp @@ -0,0 +1,9 @@ +#pragma once + +#include "object_wrapper.hpp" + +template +std::shared_ptr ObjectWrapper::get() const +{ + return ObjectImpl::resolve(_container); +} -- cgit v1.2.3-18-g5258