QtMvvm  1.0.0
A mvvm oriented library for Qt, to create Projects for Widgets and Quick in parallel
serviceregistry.h
1 #ifndef QTMVVM_SERVICEREGISTRY_H
2 #define QTMVVM_SERVICEREGISTRY_H
3 
4 #include <functional>
5 
6 #include <QtCore/qscopedpointer.h>
7 #include <QtCore/qvariant.h>
8 #include <QtCore/qexception.h>
9 
10 #include "QtMvvmCore/qtmvvmcore_global.h"
11 #include "QtMvvmCore/injection.h"
12 
13 namespace QtMvvm {
14 
15 class ServiceRegistryPrivate;
17 class Q_MVVMCORE_EXPORT ServiceRegistry
18 {
19 public:
21  ServiceRegistry(ServiceRegistryPrivate *d_ptr);
22  ~ServiceRegistry();
23 
25  static ServiceRegistry* instance();
26 
28  template <typename TInterface>
29  bool isRegistered() const;
31  bool isRegistered(const QByteArray &iid) const;
32 
34  template <typename TInterface, typename TService>
35  void registerInterface(bool weak = false);
37  template <typename TInterface, typename TService, typename TFunc>
38  void registerInterface(const TFunc &fn, bool weak = false);
40  template <typename TInterface, typename TService>
41  void registerInterface(TService *service, bool weak = false);
43  template <typename TService>
44  void registerObject(bool weak = false);
46  template <typename TService, typename TFunc>
47  void registerObject(const TFunc &fn, bool weak = false);
49  template <typename TService>
50  void registerObject(TService *service, bool weak = false);
51 
53  void registerService(const QByteArray &iid,
54  const QMetaObject *metaObject,
55  bool weak = false);
57  void registerService(const QByteArray &iid,
58  const std::function<QObject*(const QObjectList &)> &fn,
59  QByteArrayList injectables,
60  bool weak = false);
61 
63  template <typename TInterface>
64  TInterface *service();
66  QObject *serviceObj(const QByteArray &iid);
67 
69  void injectServices(QObject *object);
71  template <typename TClass>
72  TClass *constructInjected(QObject *parent = nullptr);
74  QObject *constructInjected(const QMetaObject *metaObject, QObject *parent = nullptr);
75 
76 private:
77  friend class QtMvvm::ServiceRegistryPrivate;
79 };
80 
82 class Q_MVVMCORE_EXPORT ServiceExistsException : public QException
83 {
84 public:
87 
89  const char *what() const noexcept override;
90 
92  void raise() const override;
94  QException *clone() const override;
95 
96 protected:
99 
101  const QByteArray _msg;
102 };
103 
105 class Q_MVVMCORE_EXPORT ServiceConstructionException : public QException
106 {
107 public:
110 
112  const char *what() const noexcept override;
113 
115  void raise() const override;
117  QException *clone() const override;
118 
119 protected:
122 
124  const QByteArray _msg;
125 };
126 
129 {
130 public:
133 
134  void raise() const override;
135  QException *clone() const override;
136 
137 protected:
140 };
141 
142 // ------------- Generic Implementation -------------
143 
144 template<typename TInterface>
146 {
147  return isRegistered(__helpertypes::inject_iid<TInterface*>());
148 }
149 
150 #define QTMVVM_SERVICE_ASSERT(tint, tsvc) \
151  static_assert(__helpertypes::is_valid_interface<TInterface, TService>::value, "TService must implement the given TInterface interface and be a qobject class"); \
152  Q_ASSERT_X(qobject_interface_iid<TInterface*>(), Q_FUNC_INFO, "TInterface must be registered with Q_DECLARE_INTERFACE");
153 
154 template<typename TInterface, typename TService>
156 {
157  QTMVVM_SERVICE_ASSERT(TInterface, TService)
158  registerService(qobject_interface_iid<TInterface*>(), &TService::staticMetaObject, weak);
159 }
160 
161 template <typename TInterface, typename TService, typename TFunc>
162 void ServiceRegistry::registerInterface(const TFunc &fn, bool weak)
163 {
164  QTMVVM_SERVICE_ASSERT(TInterface, TService)
165  QByteArrayList injectables;
166  auto packed_fn = __helpertypes::pack_function(fn, injectables);
167  registerService(qobject_interface_iid<TInterface*>(), packed_fn, injectables, weak);
168 }
169 
170 template<typename TInterface, typename TService>
171 void ServiceRegistry::registerInterface(TService *service, bool weak)
172 {
173  QTMVVM_SERVICE_ASSERT(TInterface, TService)
174  registerService(qobject_interface_iid<TInterface*>(), [service](const QObjectList &params) -> QObject* {
175  Q_UNUSED(params);
176  return service;
177  }, QByteArrayList(), weak);
178 }
179 
180 #undef QTMVVM_SERVICE_ASSERT
181 #define QTMVVM_SERVICE_ASSERT(tsvc) \
182  static_assert(__helpertypes::is_qobj<tsvc>::value, "TService must be a qobject class");
183 
184 template<typename TService>
186 {
187  QTMVVM_SERVICE_ASSERT(TService)
188  registerService(__helpertypes::qobject_iid<TService*>(), &TService::staticMetaObject, weak);
189 }
190 
191 template<typename TService, typename TFunc>
192 void ServiceRegistry::registerObject(const TFunc &fn, bool weak)
193 {
194  QTMVVM_SERVICE_ASSERT(TService)
195  QByteArrayList injectables;
196  auto packed_fn = __helpertypes::pack_function(fn, injectables);
197  registerService(__helpertypes::qobject_iid<TService*>(), packed_fn, injectables, weak);
198 }
199 
200 template<typename TService>
201 void ServiceRegistry::registerObject(TService *service, bool weak)
202 {
203  QTMVVM_SERVICE_ASSERT(TService)
204  registerService(__helpertypes::qobject_iid<TService*>(), [service](const QObjectList &params) -> QObject* {
205  Q_UNUSED(params);
206  return service;
207  }, QByteArrayList(), weak);
208 }
209 
210 #undef QTMVVM_SERVICE_ASSERT
211 
212 template<typename TInterface>
214 {
215  return qobject_cast<TInterface*>(serviceObj(__helpertypes::inject_iid<TInterface*>()));
216 }
217 
218 template<typename TClass>
220 {
221  static_assert(__helpertypes::is_qobj<TClass>::value, "TClass must be a qobject class");
222  return qobject_cast<TClass*>(constructInjected(&TClass::staticMetaObject, parent));
223 }
224 
225 }
226 
227 #endif // QTMVVM_SERVICEREGISTRY_H
void registerObject(bool weak=false)
Register a service via its type.
TClass * constructInjected(QObject *parent=nullptr)
Constructs a new instance of TClass with properties injected.
Is thrown if a service could not be created because of a missing dependency to be injected...
bool isRegistered() const
Checks if a given interface or service is already registered.
Is thrown if a service is beeing registered that is already registered.
A singleton to prepare services for dependency injection and to access them.
void registerService(const QByteArray &iid, const QMetaObject *metaObject, bool weak=false)
Register a service by an iid via their metadata.
TInterface * service()
Returns the service for the given interface.
Is thrown in case the construction of a service has failed.
QObject * serviceObj(const QByteArray &iid)
Returns the service for the given iid.
The primary namespace of the QtMvvm library.
Definition: binding.h:10
void registerInterface(bool weak=false)
Register a service for its interface via the type.