|
|
@ -2,6 +2,8 @@ |
|
|
|
#include "serviceregistry_p.h" |
|
|
|
|
|
|
|
#include <QtCore/QGlobalStatic> |
|
|
|
#include <QtCore/QRegularExpression> |
|
|
|
#include <QtCore/QMetaProperty> |
|
|
|
|
|
|
|
using namespace QtMvvm; |
|
|
|
|
|
|
@ -19,17 +21,88 @@ ServiceRegistry *ServiceRegistry::instance() |
|
|
|
|
|
|
|
void ServiceRegistry::registerService(const QByteArray &iid, const QMetaObject *metaObject) |
|
|
|
{ |
|
|
|
//TODO create function with injectables and pass to other overload
|
|
|
|
QMutexLocker _(&d->serviceMutex); |
|
|
|
Q_ASSERT(!d->services.contains(iid)); //TODO exception
|
|
|
|
d->services.insert(iid, QSharedPointer<ServiceRegistryPrivate::MetaServiceInfo>::create(metaObject)); |
|
|
|
} |
|
|
|
|
|
|
|
void ServiceRegistry::registerService(const QByteArray &iid, const std::function<QObject *(const QVariantList &)> &fn, QByteArrayList injectables) |
|
|
|
void ServiceRegistry::registerService(const QByteArray &iid, const std::function<QObject*(const QObjectList &)> &fn, QByteArrayList injectables) |
|
|
|
{ |
|
|
|
|
|
|
|
QMutexLocker _(&d->serviceMutex); |
|
|
|
Q_ASSERT(!d->services.contains(iid)); //TODO exception
|
|
|
|
d->services.insert(iid, QSharedPointer<ServiceRegistryPrivate::FnServiceInfo>::create(fn, injectables)); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------- Private Implementation -------------
|
|
|
|
|
|
|
|
ServiceRegistryPrivate::ServiceRegistryPrivate() |
|
|
|
ServiceRegistryPrivate::ServiceRegistryPrivate() : |
|
|
|
serviceMutex(), |
|
|
|
services() |
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ServiceRegistryPrivate::ServiceInfo::ServiceInfo() : |
|
|
|
_instance(nullptr) |
|
|
|
{} |
|
|
|
|
|
|
|
ServiceRegistryPrivate::ServiceInfo::~ServiceInfo() |
|
|
|
{ |
|
|
|
if(_instance) |
|
|
|
QMetaObject::invokeMethod(_instance, "deleteLater"); |
|
|
|
} |
|
|
|
|
|
|
|
QObject *ServiceRegistryPrivate::ServiceInfo::instance(ServiceRegistryPrivate *d) |
|
|
|
{ |
|
|
|
if(!_instance) |
|
|
|
_instance = construct(d); |
|
|
|
return _instance; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ServiceRegistryPrivate::FnServiceInfo::FnServiceInfo(const std::function<QObject*(QObjectList)> &creator, const QByteArrayList &injectables) : |
|
|
|
creator(creator), |
|
|
|
injectables(injectables) |
|
|
|
{} |
|
|
|
|
|
|
|
QObject *ServiceRegistryPrivate::FnServiceInfo::construct(ServiceRegistryPrivate *d) const |
|
|
|
{ |
|
|
|
QObjectList params; |
|
|
|
foreach(auto inj, injectables) |
|
|
|
params.append(d->services.value(inj)->instance(d));//TODO exception
|
|
|
|
return creator(params); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ServiceRegistryPrivate::MetaServiceInfo::MetaServiceInfo(const QMetaObject *metaObject) : |
|
|
|
metaObject(metaObject) |
|
|
|
{} |
|
|
|
|
|
|
|
QObject *ServiceRegistryPrivate::MetaServiceInfo::construct(ServiceRegistryPrivate *d) const |
|
|
|
{ |
|
|
|
auto instance = metaObject->newInstance(); |
|
|
|
Q_ASSERT(instance); //TODO exception
|
|
|
|
|
|
|
|
static QRegularExpression nameRegex(QStringLiteral(R"__(^__qtmvvm_inject_(.+)$)__"), |
|
|
|
QRegularExpression::OptimizeOnFirstUsageOption); |
|
|
|
|
|
|
|
for(auto i = 0; i < metaObject->propertyCount(); i++) { |
|
|
|
auto prop = metaObject->property(i); |
|
|
|
auto match = nameRegex.match(QString::fromUtf8(prop.name())); |
|
|
|
if(match.hasMatch()) { |
|
|
|
auto tPropIndex = metaObject->indexOfProperty(qUtf8Printable(match.captured(1))); |
|
|
|
if(tPropIndex == -1) |
|
|
|
continue; //TODO warning
|
|
|
|
auto tProp = metaObject->property(tPropIndex); |
|
|
|
|
|
|
|
auto inject = prop.read(instance).toByteArray(); |
|
|
|
auto injObj = d->services.value(inject)->instance(d); //TODO exception
|
|
|
|
tProp.write(instance, QVariant::fromValue(injObj)); //TODO check if casting works
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//TODO call "init" method
|
|
|
|
return instance; |
|
|
|
} |
|
|
|