Skip to content

Commit

Permalink
update: add ServicePtr template
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-Turmoil committed Oct 1, 2023
1 parent 0c4eccd commit 25947e1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 38 deletions.
33 changes: 15 additions & 18 deletions mioc/include/mioc/ServiceContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ class ServiceContainer final
// Resolve registered service.
// nullptr returned if service not registered.
template<typename TService>
std::shared_ptr<TService> Resolve() const
ServicePtr<TService> Resolve() const
{
auto typeId = _GetTypeId<TService>();
auto it = _services.find(typeId);
if (it != _services.end())
{
auto factory = std::static_pointer_cast<ServiceFactory<TService>>(it->second);
auto factory = std::static_pointer_cast<TransientServiceFactory<TService>>(it->second);
return factory->Resolve();
}
return nullptr;
Expand All @@ -61,7 +61,7 @@ class ServiceContainer final
// Register a singleton instance.
// Will replace old registrations silently.
template<typename TInterface>
ServiceContainer* AddSingleton(std::shared_ptr<TInterface> singleton)
ServiceContainer* AddSingleton(ServicePtr<TInterface> singleton)
{
// std::map::emplace will not replace old value if key already presents.
_services[_GetTypeId<TInterface>()] = std::make_shared<SingletonServiceFactory<TInterface>>(singleton);
Expand All @@ -76,10 +76,9 @@ class ServiceContainer final
if (_lazy)
{
_AddSingletonServiceFactory(
std::function<std::shared_ptr<TInterface>(std::shared_ptr<TArguments>... args)>(
[](std::shared_ptr<TArguments>... args) -> std::shared_ptr<TInterface>
{
return std::make_shared<TConcrete>(std::forward<std::shared_ptr<TArguments>>(args)...);
std::function<ServicePtr<TInterface>(ServicePtr<TArguments>... args)>(
[](ServicePtr<TArguments>... args) -> ServicePtr<TInterface> {
return std::make_shared<TConcrete>(std::forward<ServicePtr<TArguments>>(args)...);
}));
}
else
Expand All @@ -96,10 +95,9 @@ class ServiceContainer final
ServiceContainer* AddTransient()
{
_AddTransientServiceFactory(
std::function<std::shared_ptr<TInterface>(std::shared_ptr<TArguments>... args)>(
[](std::shared_ptr<TArguments>... args) -> std::shared_ptr<TInterface>
{
return std::make_shared<TConcrete>(std::forward<std::shared_ptr<TArguments>>(args)...);
std::function<ServicePtr<TInterface>(std::shared_ptr<TArguments>... args)>(
[](ServicePtr<TArguments>... args) -> ServicePtr<TInterface> {
return std::make_shared<TConcrete>(std::forward<ServicePtr<TArguments>>(args)...);
}));

return this;
Expand All @@ -118,28 +116,27 @@ class ServiceContainer final
// Low level registration.
template<typename TInterface, typename... TDependencies>
void _AddTransientServiceFactory(
std::function<std::shared_ptr<TInterface>(std::shared_ptr<TDependencies>... dependencies)> factory)
std::function<ServicePtr<TInterface>(ServicePtr<TDependencies>... dependencies)> factory)
{
_services[_GetTypeId<TInterface>()] =
std::make_shared<ServiceFactory<TInterface>>([=] { return factory(Resolve<TDependencies>()...); });
std::make_shared<TransientServiceFactory<TInterface>>([=] { return factory(Resolve<TDependencies>()...); });
}


template<typename TInterface, typename... TDependencies>
void _AddSingletonServiceFactory(
std::function<std::shared_ptr<TInterface>(std::shared_ptr<TDependencies>... dependencies)> factory)
std::function<ServicePtr<TInterface>(ServicePtr<TDependencies>... dependencies)> factory)
{
_services[_GetTypeId<TInterface>()] =
std::make_shared<SingletonServiceFactory<TInterface>>([=]
{
return factory(Resolve<TDependencies>()...);
std::make_shared<SingletonServiceFactory<TInterface>>([=] {
return factory(Resolve<TDependencies>()...);
});
}

private:
static int _nextTypeId;

std::map<int, std::shared_ptr<IServiceFactory>> _services;
std::map<int, std::shared_ptr<ServiceFactory>> _services;
bool _lazy;
};

Expand Down
59 changes: 39 additions & 20 deletions mioc/include/mioc/ServiceFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,51 @@
MIOC_BEGIN

// Abstract representation of service factory.
class IServiceFactory
class ServiceFactory
{
public:
// A simple trick to make a class abstract.
virtual ~IServiceFactory() = 0;
virtual ~ServiceFactory() = 0;
};


inline IServiceFactory::~IServiceFactory() = default;
inline ServiceFactory::~ServiceFactory() = default;


template<typename TService>
using ServicePtr = std::shared_ptr<TService>;

template<typename TService>
using ServiceProvider = std::function<std::shared_ptr<TService>()>;
using ServiceProvider = std::function<ServicePtr<TService>()>;


// Transient service factory will create a new instance every time.
template<typename TService>
class ServiceFactory : public IServiceFactory
class TransientServiceFactory : public ServiceFactory
{
public:
explicit ServiceFactory(const ServiceProvider<TService>& provider)
explicit TransientServiceFactory(const ServiceProvider<TService>& provider)
: _provider(provider)
{
}

explicit TransientServiceFactory(ServiceProvider<TService>&& provider)
: _provider(std::move(provider))
{
}


ServiceFactory(const ServiceFactory&) = default;
ServiceFactory& operator=(const ServiceFactory&) = default;
TransientServiceFactory(const TransientServiceFactory&) = default;
TransientServiceFactory& operator=(const TransientServiceFactory&) = default;


ServiceFactory(ServiceFactory&& other) noexcept
TransientServiceFactory(TransientServiceFactory&& other) noexcept
{
_provider = std::move(other._provider);
}


ServiceFactory& operator=(ServiceFactory&& other) noexcept
TransientServiceFactory& operator=(TransientServiceFactory&& other) noexcept
{
if (this != &other)
{
Expand All @@ -58,7 +67,7 @@ class ServiceFactory : public IServiceFactory
}


~ServiceFactory() override = default;
~TransientServiceFactory() override = default;


virtual std::shared_ptr<TService> Resolve()
Expand All @@ -68,7 +77,7 @@ class ServiceFactory : public IServiceFactory

protected:
// Used by SingletonServiceFactory when instance is directly provided.
ServiceFactory() = default;
TransientServiceFactory() = default;

private:
ServiceProvider<TService> _provider;
Expand All @@ -77,17 +86,27 @@ class ServiceFactory : public IServiceFactory

// Singleton service factory will create only one instance.
template<typename TService>
class SingletonServiceFactory final : public ServiceFactory<TService>
class SingletonServiceFactory final : public TransientServiceFactory<TService>
{
public:
explicit SingletonServiceFactory(const ServiceProvider<TService>& provider)
: ServiceFactory<TService>(provider)
: TransientServiceFactory<TService>(provider)
{
}

explicit SingletonServiceFactory(ServiceProvider<TService>&& provider)
: TransientServiceFactory<TService>(std::move(provider))
{
}


explicit SingletonServiceFactory(const ServicePtr<TService>& instance)
{
_instance = instance;
}

explicit SingletonServiceFactory(std::shared_ptr<TService> instance)
: ServiceFactory<TService>()
explicit SingletonServiceFactory(ServicePtr<TService>&& instance)
: TransientServiceFactory<TService>()
{
_instance = std::move(instance);
}
Expand All @@ -98,7 +117,7 @@ class SingletonServiceFactory final : public ServiceFactory<TService>


SingletonServiceFactory(SingletonServiceFactory&& other) noexcept
: ServiceFactory<TService>(std::move(other))
: TransientServiceFactory<TService>(std::move(other))
{
_instance = std::move(other._instance);
}
Expand All @@ -108,7 +127,7 @@ class SingletonServiceFactory final : public ServiceFactory<TService>
{
if (this != &other)
{
ServiceFactory<TService>::operator=(std::move(other));
TransientServiceFactory<TService>::operator=(std::move(other));
_instance = std::move(other._instance);
}
return *this;
Expand All @@ -122,14 +141,14 @@ class SingletonServiceFactory final : public ServiceFactory<TService>
{
if (_instance == nullptr)
{
_instance = ServiceFactory<TService>::Resolve();
_instance = TransientServiceFactory<TService>::Resolve();
}

return _instance;
}

private:
std::shared_ptr<TService> _instance;
ServicePtr<TService> _instance;
};


Expand Down

0 comments on commit 25947e1

Please sign in to comment.