QtMvvm  1.1.0
A mvvm oriented library for Qt, to create Projects for Widgets and Quick in parallel
Public Types | Public Member Functions | Static Public Member Functions | List of all members
QtMvvm::ServiceRegistry Class Reference

A singleton to prepare services for dependency injection and to access them. More...

#include <serviceregistry.h>

Public Types

enum  DestructionScope { DestroyOnAppQuit = 1, DestroyOnAppDestroy = 2, DestroyOnRegistryDestroy = 3, DestroyNever = 127 }
 A scope to indicate when a service should be deleted. More...
 

Public Member Functions

template<typename TInterface >
bool isRegistered () const
 Checks if a given interface or service is already registered.
 
bool isRegistered (const QByteArray &iid) const
 Checks if a given interface or service is already registered.
 
template<typename TInterface , typename TService >
void registerInterface (DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service for its interface via the type. More...
 
template<typename TInterface , typename TService , typename TFunc >
void registerInterface (TFunc fn, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service for its interface via a constructor function. More...
 
template<typename TInterface , typename TService >
void registerInterface (TService *service, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service for its interface via an already existing instance. More...
 
template<typename TService >
void registerObject (DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service via its type. More...
 
template<typename TService , typename TFunc >
void registerObject (TFunc fn, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service via a constructor function. More...
 
template<typename TService >
void registerObject (TService *service, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service via an already existing instance. More...
 
template<typename TInterface >
void registerPlugin (QString pluginType={}, QString pluginKey={}, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service via specifing a plugin to be loaded. More...
 
void registerService (const QByteArray &iid, const QMetaObject *metaObject, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service by an iid via their metadata. More...
 
Q_DECL_DEPRECATED void registerService (const QByteArray &iid, const QMetaObject *metaObject, bool weak)
 
void registerService (const QByteArray &iid, const std::function< QObject *(const QObjectList &)> &fn, QByteArrayList injectables, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service by an iid via a generalized constructor function. More...
 
Q_DECL_DEPRECATED void registerService (const QByteArray &iid, const std::function< QObject *(const QObjectList &)> &fn, QByteArrayList injectables, bool weak)
 
void registerService (QByteArray iid, QString pluginType={}, QString pluginKey={}, DestructionScope scope=DestroyOnAppDestroy, bool weak=false)
 Register a service by an iid via specifing a plugin to be loaded. More...
 
template<typename TInterface >
TInterface * service ()
 Returns the service for the given interface. More...
 
QObjectserviceObj (const QByteArray &iid)
 Returns the service for the given iid. More...
 
void injectServices (QObject *object)
 Inject services for all injectable properties on object. More...
 
template<typename TClass >
TClass * constructInjected (QObject *parent=nullptr)
 Constructs a new instance of TClass with properties injected. More...
 
QObjectconstructInjected (const QMetaObject *metaObject, QObject *parent=nullptr)
 Constructs a new instance of metaObject with properties injected. More...
 

Static Public Member Functions

static ServiceRegistryinstance ()
 Returns the ServiceRegistry singleton instance.
 

Detailed Description

A singleton to prepare services for dependency injection and to access them.

This is the class responsible for the dependency injection (DI) part. All services registered with the registry are available for DI. When using lazy initialization, services themselves can also have dependencies to be injected. When the registry creates them it will automatically inject them. Automatic DI is also done for ViewModel created by the CoreApp.

Note
If a service has a slot named qtmvvm_init() it is called automatically by the registry right after all dependant services have been injected.

The following example shows how to use DI. The first shows how to use it with a simple, interface-less service for an already created object:

// service.h
class Service : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE explicit Service(QObject *parent = nullptr); //required signature
public Q_SLOTS:
void baum();
void qtmvvm_init(); //is called by the registry
};
// myclass.h
class MyClass : public QObject
{
Q_OBJECT
QTMVVM_INJECT_PROP(Service*, service, _service)
//...
private:
Service *_service;
};
//main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//...
auto myObj = new MyClass(parent);
// _service is now initialized via a valid Service
}

The second example shows how to use it for interface based services and on objects that are created via the registry:

// iservice.h
class IService
{
public:
virtual inline ~IService() = default;
public Q_SLOTS:
virtual void baum() = 0;
};
#define IServiceIid "com.example.myapp.IService"
Q_DECLARE_INTERFACE(IService, IServiceIid)
// service.h
class Service : public QObject, public IService
{
Q_OBJECT
Q_INTERFACES(IService)
public:
Q_INVOKABLE explicit Service(QObject *parent = nullptr); //required signature
public Q_SLOTS:
void baum() override;
void qtmvvm_init(); //is called by the registry
};
// myclass.h
class MyClass : public QObject
{
Q_OBJECT
QTMVVM_INJECT_PROP(IService*, service, _service)
public:
Q_INVOKABLE MyClass(QObject *parent = nullptr); //required signature
//...
private:
IService *_service;
};
//main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtMvvm::registerInterfaceConverter<IService>();
//...
// _service is now initialized via a valid IService
}
See also
QtMvvm::registerInterfaceConverter, QTMVVM_INJECT, QTMVVM_INJECT_PROP, ViewModel

Definition at line 17 of file serviceregistry.h.

Member Enumeration Documentation

◆ DestructionScope

A scope to indicate when a service should be deleted.

Enumerator
DestroyOnAppQuit 

Destroy when the QCoreApplication::aboutToQuit signal is emitted.

DestroyOnAppDestroy 

Destroy as soon as the QCoreApplication gets destroyed (typically end of main)

DestroyOnRegistryDestroy 

Destroy together with the service registry instance (static memory, unspecified order!)

DestroyNever 

Never destroy the instance.

Definition at line 21 of file serviceregistry.h.

Member Function Documentation

◆ constructInjected() [1/2]

template<typename TClass >
QtMvvm::ServiceRegistry::constructInjected ( QObject parent = nullptr)

Constructs a new instance of TClass with properties injected.

Template Parameters
TClassThe type of object to be created, must extend QObject
Parameters
parentThe parent object of the created object
Returns
A newly created instance of TClass.
Exceptions
ServiceConstructionExceptionIf the registry failed to create an instance that needs to be injected into the object

First the method creates a new instance of TClass, then loads all services that are needed to inject into properties of the object that are marked for injection via QTMVVM_INJECT. If any lazy service has not been created yet, it is created on the fly and then injected. The returned object is parented to the parent object. If that is null it is owned by the caller.

Attention
For this to work, the TClass must have an invokable constructor with the following signature: Q_INVOKABLE explicit TClass(QObject *parent = nullptr);
See also
ServiceRegistry::injectServices, ServiceRegistry::service, QTMVVM_INJECT, QTMVVM_INJECT_PROP

Definition at line 254 of file serviceregistry.h.

◆ constructInjected() [2/2]

QtMvvm::ServiceRegistry::constructInjected ( const QMetaObject metaObject,
QObject parent = nullptr 
)

Constructs a new instance of metaObject with properties injected.

Parameters
metaObjectThe metaobject of object type to be created, must extend QObject
parentThe parent object of the created object
Returns
A newly created instance of the given type.
Exceptions
ServiceConstructionExceptionIf the registry failed to create an instance that needs to be injected into the object

First the method creates a new instance of metaObject, then loads all services that are needed to inject into properties of the object that are marked for injection via QTMVVM_INJECT. If any lazy service has not been created yet, it is created on the fly and then injected. The returned object is parented to the parent object. If that is null it is owned by the caller.

Attention
For this to work, the class defined by metaObject must have an invokable constructor with the following signature: Q_INVOKABLE explicit TClass(QObject *parent = nullptr);
See also
ServiceRegistry::injectServices, ServiceRegistry::service, QTMVVM_INJECT, QTMVVM_INJECT_PROP

◆ injectServices()

QtMvvm::ServiceRegistry::injectServices ( QObject object)

Inject services for all injectable properties on object.

Parameters
objectThe object to inject properties into
Exceptions
ServiceConstructionExceptionIf the registry failed to create an instance that needs to be injected into the object

Loads all services that are needed to inject into properties of the object that are marked for injection via QTMVVM_INJECT. If any lazy service has not been created yet, it is created on the fly and then injected.

See also
ServiceRegistry::constructInjected, ServiceRegistry::service, QTMVVM_INJECT, QTMVVM_INJECT_PROP

◆ registerInterface() [1/3]

template<typename TInterface , typename TService >
QtMvvm::ServiceRegistry::registerInterface ( DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service for its interface via the type.

Template Parameters
TInterfaceThe interface type to register the service for
TServiceThe service to be registered for that interface. Must extend QObject and implement TInterface
Parameters
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TInterface

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service is lazy initialized an will be created as soon as it is requested for the first time. If it has any injectable properties, they will be automatically injected on construction.

If the service is registered as weak, registering another service for the same interface will not throw an exception but instead discard (and delete) this one.

Attention
Make shure to register TInterface via QtMvvm::registerInterfaceConverter, otherwise injection for the interface is not possible. In addition to this, TService must have an invokable constructor with the following signature: Q_INVOKABLE explicit TService(QObject *parent = nullptr);
See also
ServiceRegistry::registerPlugin, ServiceRegistry::registerObject, QtMvvm::registerInterfaceConverter, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 184 of file serviceregistry.h.

◆ registerInterface() [2/3]

template<typename TInterface , typename TService , typename TFunc >
QtMvvm::ServiceRegistry::registerInterface ( TFunc  fn,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service for its interface via a constructor function.

Template Parameters
TInterfaceThe interface type to register the service for
TServiceThe service to be registered for that interface. Must extend QObject and implement TInterface
TFuncThe function type of the fn parameter.
Parameters
fnThe function to be called to construct the service
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TInterface

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service is lazy initialized an will be created as soon as it is requested for the first time. It is created by calling the given fn function.

fn must have the following signature:

TService *fn(...);

TService is the template parameter of this function. The arguments are variable, but if arguments are present, they all must be pointers of types that are injectable via the registry. When the function is called internally, the registry will "inject" all services as parameters of this function.

If the service is registered as weak, registering another service for the same interface will not throw an exception but instead discard (and delete) this one.

Attention
Make shure to register TInterface via QtMvvm::registerInterfaceConverter, otherwise injection for the interface is not possible.
See also
ServiceRegistry::registerPlugin, ServiceRegistry::registerObject, QtMvvm::registerInterfaceConverter, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 191 of file serviceregistry.h.

◆ registerInterface() [3/3]

template<typename TInterface , typename TService >
QtMvvm::ServiceRegistry::registerInterface ( TService *  service,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service for its interface via an already existing instance.

Template Parameters
TInterfaceThe interface type to register the service for
TServiceThe service to be registered for that interface. Must extend QObject and implement TInterface
Parameters
serviceThe service instance to be registered as service
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TInterface

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service instance is from that point on owned by the registry. No DI is performed on the passed service.

If the service is registered as weak, registering another service for the same interface will not throw an exception but instead discard (and delete) this one.

Attention
Make shure to register TInterface via QtMvvm::registerInterfaceConverter, otherwise injection for the interface is not possible.
See also
ServiceRegistry::registerPlugin, ServiceRegistry::registerObject, QtMvvm::registerInterfaceConverter, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 200 of file serviceregistry.h.

◆ registerObject() [1/3]

template<typename TService >
QtMvvm::ServiceRegistry::registerObject ( DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service via its type.

Template Parameters
TServiceThe service to be registered by its own type. Must extend QObject
Parameters
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TService

If the function returns successfully, from now on a service of the given type can be accessed via the registry. The service is lazy initialized an will be created as soon as it is requested for the first time. If it has any injectable properties, they will be automatically injected on construction.

If the service is registered as weak, registering another service for the same TService will not throw an exception but instead discard (and delete) this one.

Attention
In order to be able to create the service, TService must have an invokable constructor with the following signature: Q_INVOKABLE explicit TService(QObject *parent = nullptr);
See also
ServiceRegistry::registerInterface, ServiceRegistry::registerPlugin, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 214 of file serviceregistry.h.

◆ registerObject() [2/3]

template<typename TService , typename TFunc >
QtMvvm::ServiceRegistry::registerObject ( TFunc  fn,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service via a constructor function.

Template Parameters
TServiceThe service to be registered by its own type. Must extend QObject
TFuncThe function type of the fn parameter.
Parameters
fnThe function to be called to construct the service
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TService

If the function returns successfully, from now on a service of the given type can be accessed via the registry. The service is lazy initialized an will be created as soon as it is requested for the first time. It is created by calling the given fn function.

fn must have the following signature:

TService *fn(...);

TService is the template parameter of this function. The arguments are variable, but if arguments are present, they all must be pointers of types that are injectable via theregistry. When the function is called internally, the registry will "inject" all services as parameters of this function.

If the service is registered as weak, registering another service for the same TService will not throw an exception but instead discard (and delete) this one.

See also
ServiceRegistry::registerInterface, ServiceRegistry::registerPlugin, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 221 of file serviceregistry.h.

◆ registerObject() [3/3]

template<typename TService >
QtMvvm::ServiceRegistry::registerObject ( TService *  service,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service via an already existing instance.

Template Parameters
TServiceThe service to be registered by its own type. Must extend QObject
Parameters
serviceThe service instance to be registered as service
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TService

If the function returns successfully, from now on a service of the given type can be accessed via the registry. The service instance is from that point on owned by the registry. No DI is performed on the passed service.

If the service is registered as weak, registering another service for the same TService will not throw an exception but instead discard (and delete) this one.

Attention
Make shure to register TInterface via QtMvvm::registerInterfaceConverter, otherwise injection for the interface is not possible.
See also
ServiceRegistry::registerInterface, ServiceRegistry::registerPlugin, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 230 of file serviceregistry.h.

◆ registerPlugin()

template<typename TInterface >
QtMvvm::ServiceRegistry::registerPlugin ( QString  pluginType = {},
QString  pluginKey = {},
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service via specifing a plugin to be loaded.

Template Parameters
TInterfaceThe interface type to register the service for
Parameters
pluginTypeThe kind of plugin to be loaded. Corresponds to the subdirectoy to find the plugin in
pluginKeyThe key to select the plugin by, if multiple are available
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for TInterface

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service is lazy initialized an will be created as soon as it is requested for the first time. If it has any injectable properties, they will be automatically injected on construction.

If the service is registered as weak, registering another service for the same interface will not throw an exception but instead discard (and delete) this one.

To actually create the instance, the registry will try to find a matching plugin to load and instanciate it. The two parameters, pluginType and pluginKey are used to select a plugin.

pluginType referes to the kind of plugin, i.e. "imageformats", "platforms", ... The value can either be a relative path, which means it is resolved relative to the standard plugin directories the application uses to find Qt plugins (pluginType can be empty to directly look in the root folders). If the path is absolute, only that absolute folder is searched. For both cases, the search is non-recursive.

pluginKey is a key to select the actual plugin files from all the plugins available in the folder identified by pluginType. For that, the "Key" property of the metadata of each plugin is checked to find one that has the given key in the list. If not specified, one of the available plugins is randomly choosen.

See also
ServiceRegistry::registerInterface, ServiceRegistry::registerObject, QtMvvm::registerInterfaceConverter, ServiceRegistry::registerService, ServiceRegistry::service

Definition at line 242 of file serviceregistry.h.

◆ registerService() [1/3]

QtMvvm::ServiceRegistry::registerService ( const QByteArray iid,
const QMetaObject metaObject,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service by an iid via their metadata.

Parameters
iidThe interface id of the type to register the service for
metaObjectThe metaobject of the service to be registered for that interface. Must extend QObject and implement the interface of iid, unless it is the id of the service itself
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for the iid

If the function returns successfully, from now on a service of the given metobject can be accessed via the registry for the iid. The service is lazy initialized an will be created as soon as it is requested for the first time. If it has any injectable properties, they will be automatically injected on construction.

If the service is registered as weak, registering another service for the same iid will not throw an exception but instead discard (and delete) this one.

Attention
In order to be able to create the service, the class defined by the metaobject must have an invokable constructor with the following signature: Q_INVOKABLE explicit Service(QObject *parent = nullptr);
See also
QtMvvm::registerInterface, ServiceRegistry::registerObject, ServiceRegistry::registerPlugin, ServiceRegistry::serviceObj

◆ registerService() [2/3]

QtMvvm::ServiceRegistry::registerService ( const QByteArray iid,
const std::function< QObject *(const QObjectList &)> &  fn,
QByteArrayList  injectables,
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service by an iid via a generalized constructor function.

Parameters
iidThe interface id of the type to register the service for
fnThe function to be called to construct the service
injectablesThe iids of the parameters to be passed to fn
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for the iid

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service is lazy initialized an will be created as soon as it is requested for the first time. It is created by calling the given fn function.

The function must return an object that implements the interface of iid, unless it is the id of the service itself. The arguments are passed as object list and are determined by the injectables parameter. That is a list of iids. When the function is called internally, the registry will "inject" all services found by the iids as parameters of this function, combined to a list of objects.

If the service is registered as weak, registering another service for the same iid will not throw an exception but instead discard (and delete) this one.

See also
QtMvvm::registerInterface, ServiceRegistry::registerObject, ServiceRegistry::registerPlugin, ServiceRegistry::serviceObj

◆ registerService() [3/3]

QtMvvm::ServiceRegistry::registerService ( QByteArray  iid,
QString  pluginType = {},
QString  pluginKey = {},
DestructionScope  scope = DestroyOnAppDestroy,
bool  weak = false 
)

Register a service by an iid via specifing a plugin to be loaded.

Parameters
iidThe interface id of the type to register the service for
pluginTypeThe kind of plugin to be loaded. Corresponds to the subdirectoy to find the plugin in
pluginKeyThe key to select the plugin by, if multiple are available
scopeThe scope at which the service instance should be destroyed
weakSpecifies if the registration should be a weak one or a normal one
Exceptions
ServiceExistsExceptionIf a non-weak service has already been registered for the iid

If the function returns successfully, from now on a service of the given type can be accessed via the registry for the interface. The service is lazy initialized an will be created as soon as it is requested for the first time. If it has any injectable properties, they will be automatically injected on construction.

If the service is registered as weak, registering another service for the same interface will not throw an exception but instead discard (and delete) this one.

To actually create the instance, the registry will try to find a matching plugin to load and instanciate it. The two parameters, pluginType and pluginKey are used to select a plugin.

pluginType referes to the kind of plugin, i.e. "imageformats", "platforms", ... The value can either be a relative path, which means it is resolved relative to the standard plugin directories the application uses to find Qt plugins (pluginType can be empty to directly look in the root folders). If the path is absolute, only that absolute folder is searched. For both cases, the search is non-recursive.

pluginKey is a key to select the actual plugin files from all the plugins available in the folder identified by pluginType. For that, the "Key" property of the metadata of each plugin is checked to find one that has the given key in the list. If not specified, one of the available plugins is randomly choosen.

See also
QtMvvm::registerInterface, ServiceRegistry::registerObject, ServiceRegistry::registerPlugin, ServiceRegistry::serviceObj

◆ service()

template<typename TInterface >
QtMvvm::ServiceRegistry::service ( )

Returns the service for the given interface.

Template Parameters
TInterfaceThe interface type get an instance of
Returns
An object that implements the interface
Exceptions
ServiceConstructionExceptionIf the registry failed to create an instance for that interface

If the service is lazy inizialized and not created yet, the registry will do so. The returned service is owned by the registry. Be careful with weak services, as they may be deleted at any time. For normal services, this is never the case.

Note
TInterface can either be an actual interface or a service type, depending on what you registered it for (i.e. TInterface of the registerInterface() method and TService of the registerObject() method
See also
ServiceRegistry::registerObject, QtMvvm::registerInterface, ServiceRegistry::serviceObj, ServiceRegistry::injectServices, ServiceRegistry::constructInjected

Definition at line 248 of file serviceregistry.h.

◆ serviceObj()

QtMvvm::ServiceRegistry::serviceObj ( const QByteArray iid)

Returns the service for the given iid.

Parameters
iidThe interface id of the type to get an instance of
Returns
An object that implements the interface specified by iid
Exceptions
ServiceConstructionExceptionIf the registry failed to create an instance for that interface

If the service is lazy inizialized and not created yet, the registry will do so. The returned service is owned by the registry. Be careful with weak services, as they may be deleted at any time. For normal services, this is never the case.

Note
iid must be the identity the service has been registered for. This depends on the type itself and how it was registered.
See also
ServiceRegistry::registerService, ServiceRegistry::serviceObj, ServiceRegistry::injectServices, ServiceRegistry::constructInjected

The documentation for this class was generated from the following files: