From ac81a06787ad38d7d0d717690275c2642e33240e Mon Sep 17 00:00:00 2001 From: Paul Knopf Date: Sun, 30 Dec 2018 21:44:41 -0500 Subject: [PATCH] Support getting the base type. --- .../QmlNet/QmlNet/types/NetTypeInfo.cpp | 25 ++++++++++++++ src/native/QmlNet/QmlNet/types/NetTypeInfo.h | 4 +++ .../Types/NetTypeManagerTests.cs | 21 +++++++++++- src/net/Qml.Net/Internal/DefaultCallbacks.cs | 34 +++++++++++-------- src/net/Qml.Net/Internal/Types/NetTypeInfo.cs | 16 +++++++++ 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/native/QmlNet/QmlNet/types/NetTypeInfo.cpp b/src/native/QmlNet/QmlNet/types/NetTypeInfo.cpp index 15280736..e0447e9f 100644 --- a/src/native/QmlNet/QmlNet/types/NetTypeInfo.cpp +++ b/src/native/QmlNet/QmlNet/types/NetTypeInfo.cpp @@ -28,6 +28,16 @@ QString NetTypeInfo::getFullTypeName() { return _fullTypeName; } +QString NetTypeInfo::getBaseType() const +{ + return _baseType; +} + +void NetTypeInfo::setBaseType(const QString& baseType) +{ + _baseType = baseType; +} + QString NetTypeInfo::getClassName() { return _className; } @@ -190,6 +200,21 @@ Q_DECL_EXPORT QmlNetStringContainer* type_info_getFullTypeName(NetTypeInfoContai return createString(result); } +Q_DECL_EXPORT QmlNetStringContainer* type_info_getBaseType(NetTypeInfoContainer* netTypeInfo) +{ + auto result = netTypeInfo->netTypeInfo->getBaseType(); + return createString(result); +} + +Q_DECL_EXPORT void type_info_setBaseType(NetTypeInfoContainer* netTypeInfo, LPWCSTR baseType) +{ + if(baseType == nullptr) { + netTypeInfo->netTypeInfo->setBaseType(QString()); + } else { + netTypeInfo->netTypeInfo->setBaseType(QString::fromUtf16(baseType)); + } +} + Q_DECL_EXPORT QmlNetStringContainer* type_info_getClassName(NetTypeInfoContainer* netTypeInfo) { QString result = netTypeInfo->netTypeInfo->getClassName(); return createString(result); diff --git a/src/native/QmlNet/QmlNet/types/NetTypeInfo.h b/src/native/QmlNet/QmlNet/types/NetTypeInfo.h index d3f97ecb..3b833bea 100644 --- a/src/native/QmlNet/QmlNet/types/NetTypeInfo.h +++ b/src/native/QmlNet/QmlNet/types/NetTypeInfo.h @@ -19,6 +19,9 @@ public: QString getFullTypeName(); + QString getBaseType() const; + void setBaseType(const QString& baseType); + QString getClassName(); void setClassName(QString className); @@ -59,6 +62,7 @@ public: private: QString _fullTypeName; + QString _baseType; QString _className; NetVariantTypeEnum _variantType; bool _isArray; diff --git a/src/net/Qml.Net.Tests/Types/NetTypeManagerTests.cs b/src/net/Qml.Net.Tests/Types/NetTypeManagerTests.cs index 1c2f4cc5..7dd51838 100644 --- a/src/net/Qml.Net.Tests/Types/NetTypeManagerTests.cs +++ b/src/net/Qml.Net.Tests/Types/NetTypeManagerTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using FluentAssertions; using Qml.Net.Internal.Types; @@ -298,5 +298,24 @@ namespace Qml.Net.Tests.Types } } } + + public class TestType15 + { + } + + public class TestType16 : TestType15 + { + } + + [Fact] + public void Can_detect_base_class() + { + var type1 = NetTypeManager.GetTypeInfo(); + type1.BaseType.Should().StartWith("System.Object, "); + var type2 = NetTypeManager.GetTypeInfo(); + type2.BaseType.Should().StartWith("Qml.Net.Tests.Types.NetTypeManagerTests+TestType15, "); + var type3 = NetTypeManager.GetTypeInfo(); + type3.BaseType.Should().BeNull(); + } } } \ No newline at end of file diff --git a/src/net/Qml.Net/Internal/DefaultCallbacks.cs b/src/net/Qml.Net/Internal/DefaultCallbacks.cs index 5385dfd7..81322736 100644 --- a/src/net/Qml.Net/Internal/DefaultCallbacks.cs +++ b/src/net/Qml.Net/Internal/DefaultCallbacks.cs @@ -24,15 +24,21 @@ namespace Qml.Net.Internal using (var type = new NetTypeInfo(t)) { var typeInfo = Type.GetType(type.FullTypeName); - if (typeInfo == null) - { - throw new InvalidOperationException(); - } - + if (typeInfo == null) + { + throw new InvalidOperationException(); + } + + var baseType = typeInfo.BaseType; + if (baseType != null) + { + type.BaseType = baseType.AssemblyQualifiedName; + } + type.ClassName = typeInfo.Name; type.PrefVariantType = GetPrefVariantType(typeInfo); - + // All the methods/properties/signals are later populated when needed. } } @@ -48,11 +54,11 @@ namespace Qml.Net.Internal } // Don't grab properties and methods for system-level types. - if (Helpers.IsPrimitive(typeInfo)) - { - return; - } - + if (Helpers.IsPrimitive(typeInfo)) + { + return; + } + if (typeInfo.IsArray) { type.IsArray = true; @@ -136,7 +142,7 @@ namespace Qml.Net.Internal if (signals.ContainsKey(name)) { notifySignal = signals[name]; - + // Make sure the signal we are referencing has no parameters. if (notifySignal.ParameterCount != 0) { @@ -193,7 +199,7 @@ namespace Qml.Net.Internal var typeInfo = Type.GetType(typeName); if (typeInfo == null) throw new InvalidOperationException($"Invalid type {typeName}"); var netReference = NetReference.CreateForObject(TypeCreator.Create(typeInfo)); - + // When .NET collects this NetReference, we don't want it to delete this // handle. Ownership has been passed to the caller. return Interop.NetReference.Clone(netReference.Handle); @@ -304,7 +310,7 @@ namespace Qml.Net.Internal // Get all the parameters for the method we are invoking. var parameterTypes = method.GetAllParameters().Select(x => x.Type.FullTypeName).ToList(); - + // And find a good method to invoke. foreach (var potentialMethod in methods) { diff --git a/src/net/Qml.Net/Internal/Types/NetTypeInfo.cs b/src/net/Qml.Net/Internal/Types/NetTypeInfo.cs index 102ddb19..7cd3fb88 100644 --- a/src/net/Qml.Net/Internal/Types/NetTypeInfo.cs +++ b/src/net/Qml.Net/Internal/Types/NetTypeInfo.cs @@ -17,6 +17,12 @@ namespace Qml.Net.Internal.Types public string FullTypeName => Utilities.ContainerToString(Interop.NetTypeInfo.GetFullTypeName(Handle)); + public string BaseType + { + get => Utilities.ContainerToString(Interop.NetTypeInfo.GetBaseType(Handle)); + set => Interop.NetTypeInfo.SetBaseType(Handle, value); + } + public string ClassName { get => Utilities.ContainerToString(Interop.NetTypeInfo.GetClassName(Handle)); @@ -133,6 +139,16 @@ namespace Qml.Net.Internal.Types public delegate IntPtr GetFullTypeNameDel(IntPtr netTypeInfo); + [NativeSymbol(Entrypoint = "type_info_getBaseType")] + public GetBaseTypeDel GetBaseType { get; set; } + + public delegate IntPtr GetBaseTypeDel(IntPtr netTypeInfo); + + [NativeSymbol(Entrypoint = "type_info_setBaseType")] + public SetBaseTypeDel SetBaseType { get; set; } + + public delegate void SetBaseTypeDel(IntPtr netTypeInfo, [MarshalAs(UnmanagedType.LPWStr)]string baseType); + [NativeSymbol(Entrypoint = "type_info_setClassName")] public SetClassNameDel SetClassName { get; set; }