#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2023 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_SUPPORT_SERVICES_SERVICECONTAINER_H #define NUCLEX_SUPPORT_SERVICES_SERVICECONTAINER_H #include "Nuclex/Support/Config.h" #include "Nuclex/Support/Services/ServiceProvider.h" #include // for std::size_t #include // for std::map (storing services by std::type_info) namespace Nuclex { namespace Support { namespace Services { // ------------------------------------------------------------------------------------------- // /// Stores services provided by the application environment /// /// This class can be used by inversion of control containers to store and retrieve /// their services. It is also possible to use it directly and store and retrieve /// services manually if the application has special requirements. /// class NUCLEX_SUPPORT_TYPE ServiceContainer : public ServiceProvider { #pragma region class TypeInfoComparer /// Compares instances of std::type_info private: class TypeInfoComparer { /// Determines the relationship of two std::type_info instances /// Type info to compare on the left side /// Type info to compare on the right side /// True if the left side comes before the right side public: bool operator()(const std::type_info *left, const std::type_info *right) const { return left->before(*right) != 0; } }; #pragma endregion // class TypeInfoComparer /// Initializes a new service container public: NUCLEX_SUPPORT_API ServiceContainer() = default; /// Destroys the service container and frees all resources public: NUCLEX_SUPPORT_API virtual ~ServiceContainer() = default; /// Counts the number of services registered in the container /// The number of services the container is currently holding public: NUCLEX_SUPPORT_API std::size_t CountServices() const { return this->services.size(); } // Unhide the templated Get method from the service provider using ServiceProvider::Get; // Unhide the templated TryGet method fro mthe service provider using ServiceProvider::TryGet; /// Adds a service to the container /// Interface under which the service will be added /// Service that will be responsible for the interface public: template void Add(const std::shared_ptr &service) { Add(typeid(TService), std::any(service)); } /// Removes a service from the container /// Interface of the service that will be removed /// True if the service existed and was removed public: template bool Remove() { return Remove(typeid(TService)); } /// Looks up the specified service /// Type of service that will be looked up /// /// The specified service as a shared_ptr wrapped in an /// protected: NUCLEX_SUPPORT_API const std::any &Get( const std::type_info &serviceType ) const; /// Tries to look up the specified service /// Type of service that will be looked up /// An std::any containing the service, if found, or an empty std::any /// /// /// An empty will be returned if the specified service has not /// been activated yet (for a mere container, that means it's not in the container, /// for a factory, it means it has not been constructed yet or its lifetime requires /// that the service instance is not stored). /// /// /// If there is another problem, this method will still throw an exception. /// /// protected: NUCLEX_SUPPORT_API const std::any &TryGet(const std::type_info &serviceType) const; /// Adds a service to the container /// /// Type of the service that will be added to the container /// /// Object that provides the service protected: NUCLEX_SUPPORT_API void Add( const std::type_info &serviceType, const std::any &service ); /// Removes a service from the container /// /// Type of the service that will be removed from the container /// /// True if the service was found and removed protected: NUCLEX_SUPPORT_API bool Remove(const std::type_info &serviceType); /// Map through which services can be looked up private: typedef std::map ServiceMap; /// Services the container is currently holding private: ServiceMap services; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Support::Services #endif // NUCLEX_SUPPORT_SERVICES_SERVICECONTAINER_H