/*************************************************************************************************** Copyright (C) 2023 The Qt Company Ltd. SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only ***************************************************************************************************/ #pragma once #include "qdotnetsafemethod.h" #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" #endif #include #ifdef __GNUC__ # pragma GCC diagnostic pop #endif class QDotNetType : public QDotNetRef { public: static inline const QString &AssemblyQualifiedName = QStringLiteral("System.Type"); QDotNetType(const void *typeRef = nullptr) : QDotNetRef(typeRef) {} QDotNetType(const QDotNetType &cpySrc) : QDotNetRef(adapter().addObjectRef(&cpySrc)) {} QDotNetType &operator =(const QDotNetType &cpySrc) { QDotNetRef::operator=(cpySrc); return *this; } QDotNetType(QDotNetType &&movSrc) noexcept : QDotNetRef(std::move(movSrc)) {} QDotNetType &operator=(QDotNetType &&movSrc) noexcept { QDotNetRef::operator=(std::move(movSrc)); return *this; } QString assemblyQualifiedName() const { if (!isValid()) return QStringLiteral(""); if (!fnAssemblyQualifiedName.isValid()) { fnAssemblyQualifiedName = adapter().resolveInstanceMethod(*this, "get_AssemblyQualifiedName", { UnmanagedType::LPWStr }); strFullName = fnAssemblyQualifiedName(); } return strFullName; } QString fullName() const { if (!isValid()) return QStringLiteral(""); if (!fnFullName.isValid()) { fnFullName = adapter().resolveInstanceMethod(*this, "get_FullName", { UnmanagedType::LPWStr }); strFullName = fnFullName(); } return strFullName; } static QDotNetType typeOf(const QString &typeName) { QDotNetFunction fnGetType; return staticMethod(AssemblyQualifiedName, "GetType", fnGetType).invoke(nullptr, typeName); } template static QDotNetType typeOf() { return typeOf(T::AssemblyQualifiedName); } template static QDotNetFunction staticFieldGet(const QString &typeName, const QString &fieldName) { const QList parameters { QDotNetInbound::Parameter }; return adapter().resolveStaticFieldGet(typeName, fieldName, parameters); } template static QDotNetFunction &staticFieldGet(const QString &typeName, const QString &fieldName, QDotNetFunction &func) { if (!func.isValid()) func = staticFieldGet(typeName, fieldName); return func; } template QDotNetFunction staticFieldGet(const QString &fieldName) const { return staticFieldGet(assemblyQualifiedName(), fieldName); } template QDotNetFunction &staticFieldGet( const QString &fieldName, QDotNetFunction &func) const { if (!func.isValid()) func = staticFieldGet(fieldName); return func; } template static QDotNetFunction staticFieldSet(const QString &typeName, const QString &fieldName) { const QList parameters { QDotNetInbound::Parameter, QDotNetOutbound::Parameter }; return adapter().resolveStaticFieldSet(typeName, fieldName, parameters); } template static QDotNetFunction &staticFieldSet(const QString &typeName, const QString &fieldName, QDotNetFunction &func) { if (!func.isValid()) func = staticFieldSet(typeName, fieldName); return func; } template static QDotNetFunction staticMethod(const QString &typeName, const QString &methodName) { const QList parameters { QDotNetInbound::Parameter, QDotNetOutbound::Parameter... }; return adapter().resolveStaticMethod(typeName, methodName, parameters); } template static QDotNetFunction &staticMethod(const QString &typeName, const QString &methodName, QDotNetFunction &func) { if (!func.isValid()) func = staticMethod(typeName, methodName); return func; } template static QDotNetSafeMethod &staticMethod(const QString &typeName, const QString &methodName, QDotNetSafeMethod &func) { if (!func.isValid()) func = staticMethod(typeName, methodName); return func; } template QDotNetFunction staticMethod(const QString &methodName) const { return staticMethod(assemblyQualifiedName(), methodName); } template QDotNetFunction &staticMethod(const QString &methodName, QDotNetFunction &func) const { if (!func.isValid()) func = staticMethod(methodName); return func; } template QDotNetSafeMethod &staticMethod(const QString &methodName, QDotNetSafeMethod &func) const { if (!func.isValid()) func = staticMethod(methodName); return func; } template static QDotNetFunction constructor(const QString &typeName) { const QList parameters { QDotNetParameter(typeName, UnmanagedType::ObjectRef), QDotNetOutbound::Parameter... }; return adapter().resolveConstructor(parameters); } template static QDotNetFunction &constructor(const QString &typeName, QDotNetFunction &ctor) { if (!ctor.isValid()) ctor = constructor(typeName); return ctor; } template static QDotNetSafeMethod &constructor(const QString &typeName, QDotNetSafeMethod &ctor) { if (!ctor.isValid()) ctor = constructor(typeName); return ctor; } template QDotNetFunction constructor() const { return constructor(assemblyQualifiedName()); } template QDotNetFunction &constructor(QDotNetFunction &ctor) const { return constructor(assemblyQualifiedName(), ctor); } template QDotNetFunction &constructor(QDotNetSafeMethod &ctor) const { return constructor(assemblyQualifiedName(), ctor); } void freeTypeRef() { freeTypeRef(assemblyQualifiedName()); } static void freeTypeRef(const QString &typeName) { adapter().freeTypeRef(typeName); } template static void freeTypeRef() { freeTypeRef(T::AssemblyQualifiedName); } bool isAssignableFrom(QDotNetType c) const { if (!c.isValid()) return false; if (!fnIsAssignableFrom.isValid()) { fnIsAssignableFrom = adapter().resolveInstanceMethod(*this, "IsAssignableFrom", { UnmanagedType::Bool, QStringLiteral("System.Type") }); if (!fnIsAssignableFrom.isValid()) return false; } return fnIsAssignableFrom(c); } template bool isAssignableFrom() const { return isAssignableFrom(typeOf()); } bool isAssignableTo(QDotNetType c) const { if (!c.isValid()) return false; if (!fnIsAssignableTo.isValid()) { fnIsAssignableTo = adapter().resolveInstanceMethod(*this, "IsAssignableTo", { UnmanagedType::Bool, QStringLiteral("System.Type") }); if (!fnIsAssignableTo.isValid()) return false; } return fnIsAssignableTo(c); } template bool isAssignableTo() const { return isAssignableTo(typeOf()); } private: mutable QDotNetFunction fnAssemblyQualifiedName; mutable QDotNetFunction fnFullName; mutable QString strFullName; mutable QDotNetFunction fnIsAssignableFrom; mutable QDotNetFunction fnIsAssignableTo; }; namespace QtDotNet { template T call(const QString &type, const QString &method, TArg... arg) { return QDotNetType::staticMethod(type, method).invoke(nullptr, arg...); } }