#ifndef QTMVVM_SERVICEREGISTRY_H #define QTMVVM_SERVICEREGISTRY_H #include #include #include #include #include "QtMvvmCore/qtmvvmcore_global.h" namespace QtMvvm { class ServiceRegistryPrivate; class Q_MVVMCORE_EXPORT ServiceRegistry { public: ServiceRegistry(ServiceRegistryPrivate *d_ptr); static ServiceRegistry* instance(); template void registerInterface(); template void registerInterface(const TFunc &fn); template void registerInterface(TService *service); template void registerObject(); template void registerObject(const TFunc &fn); template void registerObject(TService *service); void registerService(const QByteArray &iid, const QMetaObject *metaObject); void registerService(const QByteArray &iid, const std::function &fn, QByteArrayList injectables); template TInterface *service(); QObject *serviceObj(const QByteArray &iid); private: friend class QtMvvm::ServiceRegistryPrivate; QScopedPointer d; }; class Q_MVVMCORE_EXPORT ServiceExistsException : public QException { public: ServiceExistsException(const QByteArray &iid); const char *what() const noexcept override; void raise() const override; QException *clone() const override; protected: ServiceExistsException(const ServiceExistsException * const other); const QByteArray _msg; }; class Q_MVVMCORE_EXPORT ServiceConstructionException : public QException { public: ServiceConstructionException(const QByteArray &message); const char *what() const noexcept override; void raise() const override; QException *clone() const override; protected: ServiceConstructionException(const ServiceConstructionException * const other); const QByteArray _msg; }; class Q_MVVMCORE_EXPORT ServiceDependencyException : public ServiceConstructionException { public: ServiceDependencyException(const QByteArray &iid); void raise() const override; QException *clone() const override; protected: ServiceDependencyException(const ServiceDependencyException * const other); }; // ------------- Generic Implementation ------------- #define QTMVVM_SERVICE_ASSERT(tint, tsvc) \ static_assert(__helpertypes::is_valid_interface::value, "TService must implement the given TInterface interface and be a qobject class"); \ Q_ASSERT_X(qobject_interface_iid(), Q_FUNC_INFO, "TInterface must be registered with Q_DECLARE_INTERFACE"); template void ServiceRegistry::registerInterface() { QTMVVM_SERVICE_ASSERT(TInterface, TService) registerService(qobject_interface_iid(), &TService::staticMetaObject); } template void ServiceRegistry::registerInterface(const TFunc &fn) { QTMVVM_SERVICE_ASSERT(TInterface, TService) QByteArrayList injectables; auto packed_fn = __helpertypes::pack_function(fn, injectables); registerService(qobject_interface_iid(), packed_fn, injectables); } template void ServiceRegistry::registerInterface(TService *service) { QTMVVM_SERVICE_ASSERT(TInterface, TService) registerService(qobject_interface_iid(), [service](const QObjectList ¶ms) -> QObject* { Q_UNUSED(params); return service; }, QByteArrayList()); } #undef QTMVVM_SERVICE_ASSERT #define QTMVVM_SERVICE_ASSERT(tsvc) \ static_assert(__helpertypes::is_qobj::value, "TService must be a qobject class"); template void ServiceRegistry::registerObject() { QTMVVM_SERVICE_ASSERT(TService) registerService(__helpertypes::qobject_iid(), &TService::staticMetaObject); } template void ServiceRegistry::registerObject(const TFunc &fn) { QTMVVM_SERVICE_ASSERT(TService) QByteArrayList injectables; auto packed_fn = __helpertypes::pack_function(fn, injectables); registerService(__helpertypes::qobject_iid(), packed_fn, injectables); } template void ServiceRegistry::registerObject(TService *service) { QTMVVM_SERVICE_ASSERT(TService) registerService(__helpertypes::qobject_iid(), [service](const QObjectList ¶ms) -> QObject* { Q_UNUSED(params); return service; }, QByteArrayList()); } #undef QTMVVM_SERVICE_ASSERT template TInterface *ServiceRegistry::service() { return qobject_cast(serviceObj(__helpertypes::inject_iid())); } } #endif // QTMVVM_SERVICEREGISTRY_H