/*********************************************************************** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "VlppReflection.h" /*********************************************************************** .\DESCRIPTABLEINTERFACES.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace collections; namespace reflection { namespace description { /*********************************************************************** description::TypeManager ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION class TypeManager : public Object, public ITypeManager { public: static vint typeVersion; protected: Dictionary> typeDescriptors; List> typeLoaders; ITypeDescriptor* rootType = nullptr; bool loaded = false; public: TypeManager() { } ~TypeManager() { Unload(); } vint GetTypeDescriptorCount()override { return typeDescriptors.Values().Count(); } ITypeDescriptor* GetTypeDescriptor(vint index)override { return typeDescriptors.Values().Get(index).Obj(); } ITypeDescriptor* GetTypeDescriptor(const WString& name)override { vint index = typeDescriptors.Keys().IndexOf(name); return index == -1 ? 0 : typeDescriptors.Values().Get(index).Obj(); } bool SetTypeDescriptor(const WString& name, Ptr typeDescriptor)override { if (typeDescriptor && name != typeDescriptor->GetTypeName()) { return false; } if (!typeDescriptors.Keys().Contains(name)) { if (typeDescriptor) { typeDescriptors.Add(name, typeDescriptor); typeVersion++; return true; } } else { if (!typeDescriptor) { typeDescriptors.Remove(name); typeVersion++; return true; } } return false; } bool AddTypeLoader(Ptr typeLoader)override { vint index = typeLoaders.IndexOf(typeLoader.Obj()); if (index == -1) { typeLoaders.Add(typeLoader); if (loaded) { auto oldTypeVersion = typeVersion; typeLoader->Load(this); typeVersion = oldTypeVersion + 1; } return true; } else { return false; } } bool RemoveTypeLoader(Ptr typeLoader)override { vint index = typeLoaders.IndexOf(typeLoader.Obj()); if (index != -1) { if (loaded) { auto oldTypeVersion = typeVersion; typeLoader->Unload(this); typeVersion = oldTypeVersion + 1; } typeLoaders.RemoveAt(index); return true; } else { return false; } } bool Load()override { if (!loaded) { loaded = true; auto oldTypeVersion = typeVersion; // TODO: (enumerable) foreach for (vint i = 0; i < typeLoaders.Count(); i++) { typeLoaders[i]->Load(this); } typeVersion = oldTypeVersion + 1; return true; } else { return false; } } bool Unload()override { if (loaded) { loaded = false; rootType = 0; auto oldTypeVersion = typeVersion; // TODO: (enumerable) foreach for (vint i = 0; i < typeLoaders.Count(); i++) { typeLoaders[i]->Unload(this); } typeVersion = oldTypeVersion + 1; typeDescriptors.Clear(); return true; } else { return false; } } bool Reload()override { Unload(); Load(); return true; } bool IsLoaded()override { return loaded; } ITypeDescriptor* GetRootType()override { if (!rootType) { rootType = description::GetTypeDescriptor(); } return rootType; } vint GetTypeVersion() override { return typeVersion; } }; vint TypeManager::typeVersion = -1; /*********************************************************************** description::TypeManager helper functions ***********************************************************************/ ITypeManager* globalTypeManager=0; bool initializedGlobalTypeManager=false; ITypeManager* GetGlobalTypeManager() { if (!initializedGlobalTypeManager) { initializedGlobalTypeManager = true; globalTypeManager = new TypeManager; } return globalTypeManager; } bool DestroyGlobalTypeManager() { if (initializedGlobalTypeManager && globalTypeManager) { delete globalTypeManager; globalTypeManager = nullptr; TypeManager::typeVersion++; return true; } else { return false; } } bool ResetGlobalTypeManager() { if (!DestroyGlobalTypeManager()) return false; initializedGlobalTypeManager = false; return true; } ITypeDescriptor* GetTypeDescriptor(const WString& name) { if (globalTypeManager) { if (!globalTypeManager->IsLoaded()) { globalTypeManager->Load(); } return globalTypeManager->GetTypeDescriptor(name); } return nullptr; } /*********************************************************************** Cpp Helper Functions ***********************************************************************/ WString CppGetFullName(ITypeDescriptor* type) { if (auto cpp = type->GetCpp()) { if (cpp->GetFullName() == L"void" || cpp->GetFullName() == L"vl::reflection::description::VoidValue") { return L"void"; } else if (cpp->GetFullName() == L"float") { return L"float"; } else if (cpp->GetFullName() == L"double") { return L"double"; } else if (cpp->GetFullName() == L"bool") { return L"bool"; } else if (cpp->GetFullName() == L"wchar_t") { return L"wchar_t"; } else { return L"::" + cpp->GetFullName(); } } else { return L"::vl::" + type->GetTypeName(); } } WString CppGetReferenceTemplate(IPropertyInfo* prop) { if (auto cpp = prop->GetCpp()) { return cpp->GetReferenceTemplate(); } else if ((prop->GetOwnerTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined) { return WString::Unmanaged(L"$This->$Name"); } else { return WString::Unmanaged(L"$This.$Name"); } } WString CppGetClosureTemplate(IMethodInfo* method) { if (auto cpp = method->GetCpp()) { return cpp->GetClosureTemplate(); } if (method->IsStatic()) { return WString::Unmanaged(L"::vl::Func<$Func>(&$Type::$Name)"); } else { return WString::Unmanaged(L"::vl::Func<$Func>($This, &$Type::$Name)"); } } WString CppGetInvokeTemplate(IMethodInfo* method) { if (auto cpp = method->GetCpp()) { return cpp->GetInvokeTemplate(); } if (method->GetOwnerMethodGroup() == method->GetOwnerTypeDescriptor()->GetConstructorGroup()) { return WString::Unmanaged(L"new $Type($Arguments)"); } else if (method->IsStatic()) { return WString::Unmanaged(L"$Type::$Name($Arguments)"); } else { return WString::Unmanaged(L"$This->$Name($Arguments)"); } } WString CppGetAttachTemplate(IEventInfo* ev) { auto cpp = ev->GetCpp(); return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventAttach($This->$Name, $Handler)") : cpp->GetAttachTemplate(); } WString CppGetDetachTemplate(IEventInfo* ev) { auto cpp = ev->GetCpp(); return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventDetach($This->$Name, $Handler)") : cpp->GetDetachTemplate(); } WString CppGetInvokeTemplate(IEventInfo* ev) { auto cpp = ev->GetCpp(); return cpp == nullptr ? WString::Unmanaged(L"::vl::__vwsn::EventInvoke($This->$Name)($Arguments)") : cpp->GetInvokeTemplate(); } bool CppExists(ITypeDescriptor* type) { auto cpp = type->GetCpp(); return cpp == nullptr || cpp->GetFullName() != L"*"; } bool CppExists(IPropertyInfo* prop) { if (auto cpp = prop->GetCpp()) { return cpp->GetReferenceTemplate() != L"*"; } else if (auto method = prop->GetGetter()) { return CppExists(method); } else { return true; } } bool CppExists(IMethodInfo* method) { auto cpp = method->GetCpp(); return cpp == nullptr || cpp->GetInvokeTemplate() != L"*"; } bool CppExists(IEventInfo* ev) { auto cpp = ev->GetCpp(); return cpp == nullptr || cpp->GetInvokeTemplate() != L"*"; } #endif } } } /*********************************************************************** .\DESCRIPTABLEINTERFACES_LOG.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { namespace reflection { namespace description { using namespace collections; #ifndef VCZH_DEBUG_NO_REFLECTION /*********************************************************************** LogTypeManager (enum) ***********************************************************************/ void LogTypeManager_Enum(stream::TextWriter& writer, ITypeDescriptor* type) { if (type->GetTypeDescriptorFlags() == TypeDescriptorFlags::FlagEnum) { writer.WriteLine(L"@Flags"); } writer.WriteLine(L"enum " + type->GetTypeName() + L" {"); auto enumType = type->GetEnumType(); for (vint j = 0; j < enumType->GetItemCount(); j++) { writer.WriteLine(L" " + enumType->GetItemName(j) + L" = " + u64tow(enumType->GetItemValue(j)) + L","); } writer.WriteLine(L"}"); } /*********************************************************************** LogTypeManager (struct) ***********************************************************************/ void LogTypeManager_Property(stream::TextWriter& writer, IPropertyInfo* info) { if (auto cpp = info->GetCpp()) { writer.WriteLine(L" @ReferenceTemplate:" + cpp->GetReferenceTemplate()); } writer.WriteString(L" property " + info->GetName() + L" : " + info->GetReturn()->GetTypeFriendlyName()); if (info->IsReadable() && info->IsWritable() && !info->GetGetter() && !info->GetSetter() && !info->GetValueChangedEvent()) { writer.WriteLine(L";"); } else { writer.WriteString(L" { "); if (info->IsReadable()) { writer.WriteString(L"get"); if (auto mi = info->GetGetter()) { writer.WriteString(L":" + mi->GetName()); } writer.WriteString(L" "); } if (info->IsWritable()) { writer.WriteString(L"set"); if (auto mi = info->GetSetter()) { writer.WriteString(L":" + mi->GetName()); } writer.WriteString(L" "); } if (auto ei = info->GetValueChangedEvent()) { writer.WriteString(L"event:" + ei->GetName() + L" "); } writer.WriteLine(L"}"); } } void LogTypeManager_Struct(stream::TextWriter& writer, ITypeDescriptor* type) { writer.WriteLine(L"struct " + type->GetTypeName() + L" {"); for (vint j = 0; jGetPropertyCount(); j++) { IPropertyInfo* info = type->GetProperty(j); LogTypeManager_Property(writer, info); } writer.WriteLine(L"}"); } /*********************************************************************** LogTypeManager (data) ***********************************************************************/ void LogTypeManager_Data(stream::TextWriter& writer, ITypeDescriptor* type) { writer.WriteLine(L"primitive " + type->GetTypeName() + L";"); } /*********************************************************************** LogTypeManager (class) ***********************************************************************/ void LogTypeManager_PrintEvents(stream::TextWriter& writer, ITypeDescriptor* type) { bool printed = false; for (vint j = 0; j < type->GetEventCount(); j++) { printed = true; IEventInfo* info = type->GetEvent(j); if (auto cpp = info->GetCpp()) { writer.WriteLine(L" @AttachTemplate:" + cpp->GetAttachTemplate()); writer.WriteLine(L" @DetachTemplate:" + cpp->GetDetachTemplate()); writer.WriteLine(L" @InvokeTemplate:" + cpp->GetInvokeTemplate()); } writer.WriteString(L" event " + info->GetName() + L" : " + info->GetHandlerType()->GetTypeFriendlyName()); if (info->GetObservingPropertyCount() > 0) { writer.WriteLine(L" observing {"); vint count = info->GetObservingPropertyCount(); for (vint i = 0; i < count; i++) { writer.WriteLine(L" " + info->GetObservingProperty(i)->GetName() + L","); } writer.WriteLine(L" }"); } else { writer.WriteLine(L";"); } } if (printed) { writer.WriteLine(L""); } } void LogTypeManager_PrintProperties(stream::TextWriter& writer, ITypeDescriptor* type) { bool printed = false; for (vint j = 0; j < type->GetPropertyCount(); j++) { printed = true; IPropertyInfo* info = type->GetProperty(j); LogTypeManager_Property(writer, info); } if (printed) { writer.WriteLine(L""); } } void LogTypeManager_Method(stream::TextWriter& writer, IMethodInfo* info, const wchar_t* title) { if (auto cpp = info->GetCpp()) { writer.WriteLine(L" @InvokeTemplate:" + cpp->GetInvokeTemplate()); writer.WriteLine(L" @ClosureTemplate:" + cpp->GetClosureTemplate()); } writer.WriteString(L" "); writer.WriteString(title); writer.WriteString(L" " + info->GetName() + L"("); for (vint l = 0; l < info->GetParameterCount(); l++) { if (l > 0) writer.WriteString(L", "); IParameterInfo* parameter = info->GetParameter(l); writer.WriteString(parameter->GetName() + L" : " + parameter->GetType()->GetTypeFriendlyName()); } writer.WriteLine(L") : " + info->GetReturn()->GetTypeFriendlyName() + L";"); } void LogTypeManager_PrintMethods(stream::TextWriter& writer, ITypeDescriptor* type) { bool printed = false; for (vint j = 0; j < type->GetMethodGroupCount(); j++) { IMethodGroupInfo* group = type->GetMethodGroup(j); for (vint k = 0; k < group->GetMethodCount(); k++) { printed = true; IMethodInfo* info = group->GetMethod(k); if (info->IsStatic()) { LogTypeManager_Method(writer, info, L"static function"); } else { LogTypeManager_Method(writer, info, L"function"); } } } if (printed) { writer.WriteLine(L""); } } void LogTypeManager_PrintConstructors(stream::TextWriter& writer, ITypeDescriptor* type) { if (IMethodGroupInfo* group = type->GetConstructorGroup()) { for (vint k = 0; k < group->GetMethodCount(); k++) { IMethodInfo* info = group->GetMethod(k); LogTypeManager_Method(writer, info, L"constructor"); } } } void LogTypeManager_Class(stream::TextWriter& writer, ITypeDescriptor* type) { bool acceptProxy = false; bool isInterface = (type->GetTypeDescriptorFlags() & TypeDescriptorFlags::InterfaceType) != TypeDescriptorFlags::Undefined; writer.WriteString((isInterface ? L"interface " : L"class ") + type->GetTypeName()); for (vint j = 0; jGetBaseTypeDescriptorCount(); j++) { writer.WriteString(j == 0 ? L" : " : L", "); writer.WriteString(type->GetBaseTypeDescriptor(j)->GetTypeName()); } writer.WriteLine(L" {"); LogTypeManager_PrintEvents(writer, type); LogTypeManager_PrintProperties(writer, type); LogTypeManager_PrintMethods(writer, type); LogTypeManager_PrintConstructors(writer, type); writer.WriteLine(L"}"); } /*********************************************************************** LogTypeManager ***********************************************************************/ bool IsInterfaceType(ITypeDescriptor* typeDescriptor, bool& acceptProxy) { bool containsConstructor = false; if (IMethodGroupInfo* group = typeDescriptor->GetConstructorGroup()) { containsConstructor = group->GetMethodCount() > 0; if (group->GetMethodCount() == 1) { if (IMethodInfo* info = group->GetMethod(0)) { if (info->GetParameterCount() == 1 && info->GetParameter(0)->GetType()->GetTypeDescriptor()->GetTypeName() == TypeInfo::content.typeName) { acceptProxy = true; return true; } } } } if (!containsConstructor) { if (typeDescriptor->GetTypeName() == TypeInfo::content.typeName) { return true; } else { for (vint i = 0; i < typeDescriptor->GetBaseTypeDescriptorCount(); i++) { bool _acceptProxy = false; if (!IsInterfaceType(typeDescriptor->GetBaseTypeDescriptor(i), _acceptProxy)) { return false; } } const wchar_t* name = typeDescriptor->GetTypeName().Buffer(); while (const wchar_t* next = ::wcschr(name, L':')) { name = next + 1; } return name[0] == L'I' && (L'A' <= name[1] && name[1] <= L'Z'); } } return false; } void LogTypeManager(stream::TextWriter& writer) { for (vint i = 0; i < GetGlobalTypeManager()->GetTypeDescriptorCount(); i++) { ITypeDescriptor* type = GetGlobalTypeManager()->GetTypeDescriptor(i); if (auto cpp = type->GetCpp()) { writer.WriteLine(L"@FullName:" + cpp->GetFullName()); } if (type->GetValueType()) { writer.WriteLine(L"@ValueType"); } if (type->GetSerializableType()) { writer.WriteLine(L"@Serializable"); } switch (type->GetTypeDescriptorFlags()) { case TypeDescriptorFlags::Object: case TypeDescriptorFlags::IDescriptable: case TypeDescriptorFlags::Class: case TypeDescriptorFlags::Interface: LogTypeManager_Class(writer, type); break; case TypeDescriptorFlags::FlagEnum: case TypeDescriptorFlags::NormalEnum: LogTypeManager_Enum(writer, type); break; case TypeDescriptorFlags::Primitive: LogTypeManager_Data(writer, type); break; case TypeDescriptorFlags::Struct: LogTypeManager_Struct(writer, type); break; default:; } writer.WriteLine(L""); } } #endif } } } /*********************************************************************** .\DESCRIPTABLEINTERFACES_METAONLY.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION namespace vl { namespace reflection { namespace description { using namespace collections; /*********************************************************************** Context ***********************************************************************/ struct MetaonlyWriterContext { Dictionary tdIndex; Dictionary miIndex; Dictionary piIndex; Dictionary eiIndex; }; struct MetaonlyReaderContext { Dictionary> serializableTypes; List> tds; List> mis; List> pis; List> eis; }; /*********************************************************************** MetaonlyTypeInfo ***********************************************************************/ class MetaonlyTypeInfo : public Object, public ITypeInfo { friend struct stream::internal::Serialization; protected: MetaonlyReaderContext* context = nullptr; Decorator decorator = TypeDescriptor; TypeInfoHint hint = TypeInfoHint::Normal; Ptr elementType; vint typeDecriptor = -1; List> genericArguments; public: MetaonlyTypeInfo() = default; MetaonlyTypeInfo(MetaonlyWriterContext& _context, ITypeInfo* typeInfo) : decorator(typeInfo->GetDecorator()) , hint(typeInfo->GetHint()) , typeDecriptor(_context.tdIndex[typeInfo->GetTypeDescriptor()]) { if (auto et = typeInfo->GetElementType()) { elementType = Ptr(new MetaonlyTypeInfo(_context, et)); } for (vint i = 0; i < typeInfo->GetGenericArgumentCount(); i++) { auto ga = typeInfo->GetGenericArgument(i); genericArguments.Add(Ptr(new MetaonlyTypeInfo(_context, ga))); } } void SetContext(MetaonlyReaderContext* _context) { context = _context; if (elementType) { elementType->SetContext(_context); } for (vint i = 0; i < genericArguments.Count(); i++) { genericArguments[i]->SetContext(_context); } } Decorator GetDecorator() override { return decorator; } TypeInfoHint GetHint() override { return hint; } ITypeInfo* GetElementType() override { return elementType.Obj(); } ITypeDescriptor* GetTypeDescriptor() override { return context->tds[typeDecriptor].Obj(); } vint GetGenericArgumentCount() override { return genericArguments.Count(); } ITypeInfo* GetGenericArgument(vint index) override { return genericArguments[index].Obj(); } WString GetTypeFriendlyName() override { switch (decorator) { case RawPtr: return elementType->GetTypeFriendlyName() + L"*"; case SharedPtr: return elementType->GetTypeFriendlyName() + L"^"; case Nullable: return elementType->GetTypeFriendlyName() + L"?"; case TypeDescriptor: return GetTypeDescriptor()->GetTypeName(); default:; } WString result = elementType->GetTypeFriendlyName() + L"<"; // TODO: (enumerable) Linq:Aggregate for (auto [type, i] : indexed(genericArguments)) { if (i > 0) result += L", "; result += type->GetTypeFriendlyName(); } result += L">"; return result; } }; ITypeInfo* EnsureSetContext(ITypeInfo* info, MetaonlyReaderContext* context) { if (auto minfo = dynamic_cast(info)) { minfo->SetContext(context); } return info; } /*********************************************************************** Metadata ***********************************************************************/ struct IdRange { vint start = -1; vint count = 0; }; struct ParameterInfoMetadata { WString name; Ptr type; }; struct MethodInfoMetadata { WString invokeTemplate; WString closureTemplate; WString name; vint ownerTypeDescriptor = -1; vint ownerProperty = -1; List> parameters; Ptr returnType; bool isStatic = false; }; struct PropertyInfoMetadata { WString referenceTemplate; WString name; vint ownerTypeDescriptor = -1; bool isReadable = false; bool isWritable = false; Ptr returnType; vint getter = -1; vint setter = -1; vint valueChangedEvent = -1; }; struct EventInfoMetadata { WString attachTemplate; WString detachTemplate; WString invokeTemplate; WString name; vint ownerTypeDescriptor = -1; Ptr handlerType; List observingProperties; }; struct TypeDescriptorMetadata { WString fullName; WString typeName; TypeDescriptorFlags flags = TypeDescriptorFlags::Undefined; bool isAggregatable = false; bool isValueType = false; bool isSerializable = false; bool isEnumType = false; bool isFlagEnum = false; List enumItems; List enumValues; List baseTypeDescriptors; List properties; List events; List methods; List methodGroups; IdRange constructorGroup; }; } } namespace stream { namespace internal { /*********************************************************************** Serialization ***********************************************************************/ SERIALIZE_ENUM(reflection::description::ITypeInfo::Decorator) SERIALIZE_ENUM(reflection::description::TypeInfoHint) SERIALIZE_ENUM(reflection::description::TypeDescriptorFlags) BEGIN_SERIALIZATION(reflection::description::IdRange) SERIALIZE(start) SERIALIZE(count) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::MetaonlyTypeInfo) SERIALIZE(decorator) SERIALIZE(hint) SERIALIZE(elementType) SERIALIZE(typeDecriptor) SERIALIZE(genericArguments) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::ParameterInfoMetadata) SERIALIZE(name) SERIALIZE(type) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::MethodInfoMetadata) SERIALIZE(invokeTemplate) SERIALIZE(closureTemplate) SERIALIZE(name) SERIALIZE(ownerTypeDescriptor) SERIALIZE(ownerProperty) SERIALIZE(parameters) SERIALIZE(returnType) SERIALIZE(isStatic) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::PropertyInfoMetadata) SERIALIZE(referenceTemplate) SERIALIZE(name) SERIALIZE(ownerTypeDescriptor) SERIALIZE(isReadable) SERIALIZE(isWritable) SERIALIZE(returnType) SERIALIZE(getter) SERIALIZE(setter) SERIALIZE(valueChangedEvent) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::EventInfoMetadata) SERIALIZE(attachTemplate) SERIALIZE(detachTemplate) SERIALIZE(invokeTemplate) SERIALIZE(name) SERIALIZE(ownerTypeDescriptor) SERIALIZE(handlerType) SERIALIZE(observingProperties) END_SERIALIZATION BEGIN_SERIALIZATION(reflection::description::TypeDescriptorMetadata) SERIALIZE(fullName) SERIALIZE(typeName) SERIALIZE(flags) SERIALIZE(isAggregatable) SERIALIZE(isValueType) SERIALIZE(isSerializable) SERIALIZE(isEnumType) SERIALIZE(isFlagEnum) SERIALIZE(enumItems) SERIALIZE(enumValues) SERIALIZE(baseTypeDescriptors) SERIALIZE(properties) SERIALIZE(events) SERIALIZE(methods) SERIALIZE(methodGroups) SERIALIZE(constructorGroup) END_SERIALIZATION } } namespace reflection { namespace description { using Reader = stream::internal::Reader>; using Writer = stream::internal::Writer>; /*********************************************************************** IMethodInfo ***********************************************************************/ class MetaonlyParameterInfo : public Object, public IParameterInfo { protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; vint ownerTypeDescriptor = -1; IMethodInfo* ownerMethod = nullptr; public: MetaonlyParameterInfo(MetaonlyReaderContext* _context, Ptr _metadata, vint _ownerTypeDescriptor, IMethodInfo* _ownerMethod) : context(_context) , metadata(_metadata) , ownerTypeDescriptor(_ownerTypeDescriptor) , ownerMethod(_ownerMethod) { } ITypeDescriptor* GetOwnerTypeDescriptor() override { return context->tds[ownerTypeDescriptor].Obj(); } const WString& GetName() override { return metadata->name; } ITypeInfo* GetType() override { return EnsureSetContext(metadata->type.Obj(), context); } IMethodInfo* GetOwnerMethod() override { return ownerMethod; } }; class MetaonlyMethodInfo : public Object, public IMethodInfo, protected IMethodInfo::ICpp { friend class MetaonlyMethodGroupInfo; protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; IMethodGroupInfo* methodGroup = nullptr; List> parameters; public: MetaonlyMethodInfo(MetaonlyReaderContext* _context, Ptr _metadata) : context(_context) , metadata(_metadata) { // TODO: (enumerable) foreach for (vint i = 0; i < metadata->parameters.Count(); i++) { parameters.Add(Ptr(new MetaonlyParameterInfo(context, metadata->parameters[i], metadata->ownerTypeDescriptor, this))); } } // ICpp const WString& GetInvokeTemplate() override { return metadata->invokeTemplate; } const WString& GetClosureTemplate() override { return metadata->closureTemplate; } // IMemberInfo ITypeDescriptor* GetOwnerTypeDescriptor() override { return context->tds[metadata->ownerTypeDescriptor].Obj(); } const WString& GetName() override { return metadata->name; } // IMethodInfo IMethodInfo::ICpp* GetCpp() override { if (metadata->invokeTemplate.Length() + metadata->closureTemplate.Length() > 0) { return this; } return nullptr; } IMethodGroupInfo* GetOwnerMethodGroup() override { return methodGroup; } IPropertyInfo* GetOwnerProperty() override { return metadata->ownerProperty == -1 ? nullptr : context->pis[metadata->ownerProperty].Obj(); } vint GetParameterCount() override { return parameters.Count(); } IParameterInfo* GetParameter(vint index) override { return parameters[index].Obj(); } ITypeInfo* GetReturn() override { return EnsureSetContext(metadata->returnType.Obj(), context); } bool IsStatic() override { return metadata->isStatic; } void CheckArguments(collections::Array& arguments) override { CHECK_FAIL(L"Not Supported!"); } Value Invoke(const Value& thisObject, collections::Array& arguments) override { CHECK_FAIL(L"Not Supported!"); } Value CreateFunctionProxy(const Value& thisObject) override { CHECK_FAIL(L"Not Supported!"); } }; class MetaonlyMethodGroupInfo : public Object, public IMethodGroupInfo { protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; IdRange idRange; public: MetaonlyMethodGroupInfo(MetaonlyReaderContext* _context, Ptr _metadata, IdRange _idRange) : context(_context) , metadata(_metadata) , idRange(_idRange) { } // IMemberInfo ITypeDescriptor* GetOwnerTypeDescriptor() override { return GetMethod(0)->GetOwnerTypeDescriptor(); } const WString& GetName() override { return GetMethod(0)->GetName(); } // IMethodGroupInfo vint GetMethodCount() override { return idRange.count; } IMethodInfo* GetMethod(vint index) override { CHECK_ERROR(0 <= index && index < idRange.count, L"IMethodGroupInfo::GetMethod(vint)#Index out of range."); auto info = dynamic_cast(context->mis[metadata->methods[idRange.start + index]].Obj()); if (info->methodGroup == nullptr) { info->methodGroup = this; } return info; } }; /*********************************************************************** IPropertyInfo ***********************************************************************/ class MetaonlyPropertyInfo : public Object, public IPropertyInfo, protected IPropertyInfo::ICpp { protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; public: MetaonlyPropertyInfo(MetaonlyReaderContext* _context, Ptr _metadata) : context(_context) , metadata(_metadata) { } // ICpp const WString& GetReferenceTemplate() override { return metadata->referenceTemplate; } // IMemberInfo ITypeDescriptor* GetOwnerTypeDescriptor() override { return context->tds[metadata->ownerTypeDescriptor].Obj(); } const WString& GetName() override { return metadata->name; } // IPropertyInfo IPropertyInfo::ICpp* GetCpp() override { if (metadata->referenceTemplate.Length() > 0) { return this; } return nullptr; } bool IsReadable() override { return metadata->isReadable; } bool IsWritable() override { return metadata->isWritable; } ITypeInfo* GetReturn() override { return EnsureSetContext(metadata->returnType.Obj(), context); } IMethodInfo* GetGetter() override { return metadata->getter == -1 ? nullptr : context->mis[metadata->getter].Obj(); } IMethodInfo* GetSetter() override { return metadata->setter == -1 ? nullptr : context->mis[metadata->setter].Obj(); } IEventInfo* GetValueChangedEvent() override { return metadata->valueChangedEvent == -1 ? nullptr : context->eis[metadata->valueChangedEvent].Obj(); } Value GetValue(const Value& thisObject) override { CHECK_FAIL(L"Not Supported!"); } void SetValue(Value& thisObject, const Value& newValue) override { CHECK_FAIL(L"Not Supported!"); } }; /*********************************************************************** IEventInfo ***********************************************************************/ class MetaonlyEventInfo : public Object, public IEventInfo, protected IEventInfo::ICpp { protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; public: MetaonlyEventInfo(MetaonlyReaderContext* _context, Ptr _metadata) : context(_context) , metadata(_metadata) { } // ICpp const WString& GetAttachTemplate() override { return metadata->attachTemplate; } const WString& GetDetachTemplate() override { return metadata->detachTemplate; } const WString& GetInvokeTemplate() override { return metadata->invokeTemplate; } // IMemberInfo ITypeDescriptor* GetOwnerTypeDescriptor() override { return context->tds[metadata->ownerTypeDescriptor].Obj(); } const WString& GetName() override { return metadata->name; } // IEventInfo IEventInfo::ICpp* GetCpp() override { if (metadata->attachTemplate.Length() + metadata->detachTemplate.Length() + metadata->invokeTemplate.Length() > 0) { return this; } return nullptr; } ITypeInfo* GetHandlerType() override { return EnsureSetContext(metadata->handlerType.Obj(), context); } vint GetObservingPropertyCount() override { return metadata->observingProperties.Count(); } IPropertyInfo* GetObservingProperty(vint index) override { return context->pis[metadata->observingProperties[index]].Obj(); } Ptr Attach(const Value& thisObject, Ptr handler) override { CHECK_FAIL(L"Not Supported!"); } bool Detach(const Value& thisObject, Ptr handler) override { CHECK_FAIL(L"Not Supported!"); } void Invoke(const Value& thisObject, Ptr arguments) override { CHECK_FAIL(L"Not Supported!"); } }; /*********************************************************************** ITypeDescriptor ***********************************************************************/ class MetaonlyTypeDescriptor : public Object , public ITypeDescriptor , protected ITypeDescriptor::ICpp , protected IValueType , protected IEnumType { protected: MetaonlyReaderContext* context = nullptr; Ptr metadata; ISerializableType* serializableType = nullptr; List> methodGroups; Ptr constructorGroup; public: MetaonlyTypeDescriptor(MetaonlyReaderContext* _context, Ptr _metadata) : context(_context) , metadata(_metadata) { if (metadata->isSerializable) { serializableType = context->serializableTypes[metadata->typeName].Obj(); } // TODO: (enumerable) foreach for (vint i = 0; i < metadata->methodGroups.Count(); i++) { methodGroups.Add(Ptr(new MetaonlyMethodGroupInfo(context, metadata, metadata->methodGroups[i]))); } if (metadata->constructorGroup.start != -1) { constructorGroup = Ptr(new MetaonlyMethodGroupInfo(context, metadata, metadata->constructorGroup)); } } // ICpp const WString& GetFullName() override { return metadata->fullName; } // IValueType Value CreateDefault() override { CHECK_FAIL(L"Not Supported!"); } // IEnumType bool IsFlagEnum() override { return metadata->isFlagEnum; } vint GetItemCount() override { return metadata->enumItems.Count(); } WString GetItemName(vint index) override { return metadata->enumItems[index]; } vuint64_t GetItemValue(vint index) override { return metadata->enumValues[index]; } vint IndexOfItem(WString name) override { return metadata->enumItems.IndexOf(name); } Value ToEnum(vuint64_t value) override { CHECK_FAIL(L"Not Supported!"); } vuint64_t FromEnum(const Value& value) override { CHECK_FAIL(L"Not Supported!"); } // ITypeDescriptor ITypeDescriptor::ICpp* GetCpp() override { if (metadata->fullName.Length() > 0) { return this; } return nullptr; } TypeDescriptorFlags GetTypeDescriptorFlags() override { return metadata->flags; } bool IsAggregatable() override { return metadata->isAggregatable; } const WString& GetTypeName() override { return metadata->typeName; } IValueType* GetValueType() override { return metadata->isValueType ? this : nullptr; } IEnumType* GetEnumType() override { return metadata->isEnumType ? this : nullptr; } ISerializableType* GetSerializableType() override { return serializableType; } vint GetBaseTypeDescriptorCount() override { return metadata->baseTypeDescriptors.Count(); } ITypeDescriptor* GetBaseTypeDescriptor(vint index) override { return context->tds[metadata->baseTypeDescriptors[index]].Obj(); } bool CanConvertTo(ITypeDescriptor* targetType) override { if (this == targetType) return true; vint count = GetBaseTypeDescriptorCount(); for (vint i = 0; i < count; i++) { if (GetBaseTypeDescriptor(i)->CanConvertTo(targetType)) return true; } return false; } vint GetPropertyCount() override { return metadata->properties.Count(); } IPropertyInfo* GetProperty(vint index) override { return context->pis[metadata->properties[index]].Obj(); } bool IsPropertyExists(const WString& name, bool inheritable) override { return GetPropertyByName(name, inheritable); } IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable) override { for (vint i = 0; i < metadata->properties.Count(); i++) { auto info = GetProperty(i); if (info->GetName() == name) { return info; } } if (inheritable) { for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++) { if (auto info = GetBaseTypeDescriptor(i)->GetPropertyByName(name, true)) { return info; } } } return nullptr; } vint GetEventCount() override { return metadata->events.Count(); } IEventInfo* GetEvent(vint index) override { return context->eis[metadata->events[index]].Obj(); } bool IsEventExists(const WString& name, bool inheritable) override { return GetEventByName(name, inheritable); } IEventInfo* GetEventByName(const WString& name, bool inheritable) override { for (vint i = 0; i < metadata->events.Count(); i++) { auto info = GetEvent(i); if (info->GetName() == name) { return info; } } if (inheritable) { for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++) { if (auto info = GetBaseTypeDescriptor(i)->GetEventByName(name, true)) { return info; } } } return nullptr; } vint GetMethodGroupCount() override { return methodGroups.Count(); } IMethodGroupInfo* GetMethodGroup(vint index) override { return methodGroups[index].Obj(); } bool IsMethodGroupExists(const WString& name, bool inheritable) override { return GetMethodGroupByName(name, inheritable); } IMethodGroupInfo* GetMethodGroupByName(const WString& name, bool inheritable) override { // TODO: (enumerable) foreach for (vint i = 0; i < methodGroups.Count(); i++) { auto info = methodGroups[i].Obj(); if (info->GetName() == name) { return info; } } if (inheritable) { for (vint i = 0; i < metadata->baseTypeDescriptors.Count(); i++) { if (auto info = GetBaseTypeDescriptor(i)->GetMethodGroupByName(name, true)) { return info; } } } return nullptr; } IMethodGroupInfo* GetConstructorGroup() override { return constructorGroup.Obj(); } }; /*********************************************************************** GenerateMetaonlyTypes ***********************************************************************/ void GenerateMetaonlyTypeDescriptor(Writer& writer, ITypeDescriptor* td) { auto metadata = Ptr(new TypeDescriptorMetadata); if (auto cpp = td->GetCpp()) { metadata->fullName = cpp->GetFullName(); } metadata->typeName = td->GetTypeName(); metadata->flags = td->GetTypeDescriptorFlags(); metadata->isAggregatable = td->IsAggregatable(); metadata->isValueType = td->GetValueType(); metadata->isSerializable = td->GetSerializableType(); if (auto enumType = td->GetEnumType()) { metadata->isEnumType = true; metadata->isFlagEnum = enumType->IsFlagEnum(); for (vint i = 0; i < enumType->GetItemCount(); i++) { metadata->enumItems.Add(enumType->GetItemName(i)); metadata->enumValues.Add(enumType->GetItemValue(i)); } } for (vint i = 0; i < td->GetBaseTypeDescriptorCount(); i++) { metadata->baseTypeDescriptors.Add(writer.context->tdIndex[td->GetBaseTypeDescriptor(i)]); } for (vint i = 0; i < td->GetPropertyCount(); i++) { metadata->properties.Add(writer.context->piIndex[td->GetProperty(i)]); } for (vint i = 0; i < td->GetEventCount(); i++) { metadata->events.Add(writer.context->eiIndex[td->GetEvent(i)]); } for (vint i = 0; i < td->GetMethodGroupCount(); i++) { auto mg = td->GetMethodGroup(i); IdRange ir; ir.start = metadata->methods.Count(); for (vint j = 0; j < mg->GetMethodCount(); j++) { metadata->methods.Add(writer.context->miIndex[mg->GetMethod(j)]); } ir.count = metadata->methods.Count() - ir.start; metadata->methodGroups.Add(ir); } if (auto cg = td->GetConstructorGroup()) { metadata->constructorGroup.start = metadata->methods.Count(); for (vint j = 0; j < cg->GetMethodCount(); j++) { metadata->methods.Add(writer.context->miIndex[cg->GetMethod(j)]); } metadata->constructorGroup.count = metadata->methods.Count() - metadata->constructorGroup.start; } writer << metadata; } void GenerateMetaonlyMethodInfo(Writer& writer, IMethodInfo* mi) { auto metadata = Ptr(new MethodInfoMetadata); if (auto cpp = mi->GetCpp()) { metadata->invokeTemplate = cpp->GetInvokeTemplate(); metadata->closureTemplate = cpp->GetClosureTemplate(); } metadata->name = mi->GetName(); metadata->ownerTypeDescriptor = writer.context->tdIndex[mi->GetOwnerTypeDescriptor()]; if (auto pi = mi->GetOwnerProperty()) { metadata->ownerProperty = writer.context->piIndex[pi]; } for (vint i = 0; i < mi->GetParameterCount(); i++) { auto pi = mi->GetParameter(i); auto piMetadata = Ptr(new ParameterInfoMetadata); piMetadata->name = pi->GetName(); piMetadata->type = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), pi->GetType())); metadata->parameters.Add(piMetadata); } metadata->returnType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), mi->GetReturn())); metadata->isStatic = mi->IsStatic(); writer << metadata; } void GenerateMetaonlyPropertyInfo(Writer& writer, IPropertyInfo* pi) { auto metadata = Ptr(new PropertyInfoMetadata);; if (auto cpp = pi->GetCpp()) { metadata->referenceTemplate = cpp->GetReferenceTemplate(); } metadata->name = pi->GetName(); metadata->ownerTypeDescriptor = writer.context->tdIndex[pi->GetOwnerTypeDescriptor()]; metadata->isReadable = pi->IsReadable(); metadata->isWritable = pi->IsWritable(); metadata->returnType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), pi->GetReturn())); if (auto mi = pi->GetGetter()) { metadata->getter = writer.context->miIndex[mi]; } if (auto mi = pi->GetSetter()) { metadata->setter = writer.context->miIndex[mi]; } if (auto ei = pi->GetValueChangedEvent()) { metadata->valueChangedEvent = writer.context->eiIndex[ei]; } writer << metadata; } void GenerateMetaonlyEventInfo(Writer& writer, IEventInfo* ei) { auto metadata = Ptr(new EventInfoMetadata);; if (auto cpp = ei->GetCpp()) { metadata->attachTemplate = cpp->GetAttachTemplate(); metadata->detachTemplate = cpp->GetDetachTemplate(); metadata->invokeTemplate = cpp->GetInvokeTemplate(); } metadata->name = ei->GetName(); metadata->ownerTypeDescriptor = writer.context->tdIndex[ei->GetOwnerTypeDescriptor()]; metadata->handlerType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), ei->GetHandlerType())); for (vint i = 0; i < ei->GetObservingPropertyCount(); i++) { metadata->observingProperties.Add(writer.context->piIndex[ei->GetObservingProperty(i)]); } writer << metadata; } void GenerateMetaonlyTypes(stream::IStream& outputStream) { Writer writer(outputStream); writer.context = Ptr(new MetaonlyWriterContext); Dictionary tds; List mis; List pis; List eis; { auto tm = GetGlobalTypeManager(); vint count = tm->GetTypeDescriptorCount(); for (vint i = 0; i < count; i++) { auto td = tm->GetTypeDescriptor(i); tds.Add(td->GetTypeName(), td); } } { vint count = tds.Count(); for (vint i = 0; i < count; i++) { auto td = tds.Values()[i]; writer.context->tdIndex.Add(td, writer.context->tdIndex.Count()); vint mgCount = td->GetMethodGroupCount(); for (vint j = 0; j < mgCount; j++) { auto mg = td->GetMethodGroup(j); vint miCount = mg->GetMethodCount(); for (vint k = 0; k < miCount; k++) { auto mi = mg->GetMethod(k); writer.context->miIndex.Add(mi, mis.Count()); mis.Add(mi); } } if (auto cg = td->GetConstructorGroup()) { vint miCount = cg->GetMethodCount(); for (vint k = 0; k < miCount; k++) { auto mi = cg->GetMethod(k); writer.context->miIndex.Add(mi, mis.Count()); mis.Add(mi); } } vint piCount = td->GetPropertyCount(); for (vint j = 0; j < piCount; j++) { auto pi = td->GetProperty(j); writer.context->piIndex.Add(pi, pis.Count()); pis.Add(pi); } vint eiCount = td->GetEventCount(); for (vint j = 0; j < eiCount; j++) { auto ei = td->GetEvent(j); writer.context->eiIndex.Add(ei, eis.Count()); eis.Add(ei); } } } { vint tdCount = tds.Count(); vint miCount = mis.Count(); vint piCount = pis.Count(); vint eiCount = eis.Count(); writer << tdCount << miCount << piCount << eiCount; for (vint i = 0; i < tdCount; i++) { GenerateMetaonlyTypeDescriptor(writer, tds.Values()[i]); } for (vint i = 0; i < miCount; i++) { GenerateMetaonlyMethodInfo(writer, mis[i]); } for (vint i = 0; i < piCount; i++) { GenerateMetaonlyPropertyInfo(writer, pis[i]); } for (vint i = 0; i < eiCount; i++) { GenerateMetaonlyEventInfo(writer, eis[i]); } } } /*********************************************************************** LoadMetaonlyTypes ***********************************************************************/ class MetaonlyTypeLoader : public Object, public ITypeLoader { public: Ptr context; void Load(ITypeManager* manager) override { // TODO: (enumerable) foreach for (vint i = 0; i < context->tds.Count(); i++) { auto td = context->tds[i]; manager->SetTypeDescriptor(td->GetTypeName(), td); } } void Unload(ITypeManager* manager) override { } }; Ptr LoadMetaonlyTypes(stream::IStream& inputStream, const collections::Dictionary>& serializableTypes) { auto context = Ptr(new MetaonlyReaderContext); CopyFrom(context->serializableTypes, serializableTypes); auto loader = Ptr(new MetaonlyTypeLoader); loader->context = context; Reader reader(inputStream); reader.context = context; { vint tdCount = 0; vint miCount = 0; vint piCount = 0; vint eiCount = 0; reader << tdCount << miCount << piCount << eiCount; for (vint i = 0; i < tdCount; i++) { Ptr metadata; reader << metadata; context->tds.Add(Ptr(new MetaonlyTypeDescriptor(context.Obj(), metadata))); } for (vint i = 0; i < miCount; i++) { Ptr metadata; reader << metadata; context->mis.Add(Ptr(new MetaonlyMethodInfo(context.Obj(), metadata))); } for (vint i = 0; i < piCount; i++) { Ptr metadata; reader << metadata; context->pis.Add(Ptr(new MetaonlyPropertyInfo(context.Obj(), metadata))); } for (vint i = 0; i < eiCount; i++) { Ptr metadata; reader << metadata; context->eis.Add(Ptr(new MetaonlyEventInfo(context.Obj(), metadata))); } } return loader; } } } } #endif /*********************************************************************** .\DESCRIPTABLEOBJECT.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { namespace reflection { /*********************************************************************** DescriptableObject ***********************************************************************/ #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA bool DescriptableObject::IsAggregated() { return aggregationInfo != nullptr; } vint DescriptableObject::GetAggregationSize() { CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationSize()#This function should not be called on non-aggregated objects."); return aggregationSize; } DescriptableObject* DescriptableObject::GetAggregationRoot() { CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationRoot()#This function should not be called on non-aggregated objects."); return aggregationInfo[aggregationSize]; } void DescriptableObject::SetAggregationRoot(DescriptableObject* value) { CHECK_ERROR(value != nullptr, L"vl::reflection::DescriptableObject::SetAggregationRoot(Descriptable*)#The root object should not null."); CHECK_ERROR(value->IsAggregated() && value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationRoot(Descriptable*)#The root object should not have an aggregation root."); if (!IsAggregated()) { InitializeAggregation(0); } aggregationInfo[aggregationSize] = value; aggregationInfo[aggregationSize + 1] = value; for (vint i = 0; i < aggregationSize; i++) { if (aggregationInfo[i]) { aggregationInfo[i]->SetAggregationRoot(value); } } } DescriptableObject* DescriptableObject::GetAggregationParent(vint index) { CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::GetAggregationParent(vint)#This function should not be called on non-aggregated objects."); CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::GetAggregationParent(vint)#Index out of range."); return aggregationInfo[index]; } void DescriptableObject::SetAggregationParent(vint index, DescriptableObject* value) { CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#This function should not be called on non-aggregated objects."); CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Index out of range."); CHECK_ERROR(aggregationInfo[index] == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#This index has been used."); CHECK_ERROR(value != nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent should not be null."); CHECK_ERROR(!value->IsAggregated() || value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent already has a aggregation root."); CHECK_ERROR(value->referenceCounter == 0, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, DescriptableObject*)#Parent should not be contained in any smart pointer."); value->SetAggregationRoot(this); aggregationInfo[index] = value; } void DescriptableObject::SetAggregationParent(vint index, Ptr& value) { CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#This function should not be called on non-aggregated objects."); CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#Index out of range."); CHECK_ERROR(aggregationInfo[index] == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#This index has been used."); CHECK_ERROR(value, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#Parent should not be null"); CHECK_ERROR(!value->IsAggregated() || value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#Parent already has a aggregation root."); CHECK_ERROR(value->referenceCounter == 1, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr&)#Parent should not be contained in any other smart pointer."); value->SetAggregationRoot(this); auto parent = value.Detach(); aggregationInfo[index] = parent; } void DescriptableObject::InitializeAggregation(vint size) { CHECK_ERROR(!IsAggregated(), L"vl::reflection::DescriptableObject::InitializeAggregation(vint)#This function should not be called on aggregated objects."); CHECK_ERROR(size >= 0, L"vl::reflection::DescriptableObject::InitializeAggregation(vint)#Size shout not be negative."); aggregationSize = size; aggregationInfo = new DescriptableObject * [size + 2]; memset(aggregationInfo, 0, sizeof(*aggregationInfo) * (size + 2)); } #endif void DescriptableObject::FinalizeAggregation() { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (IsAggregated()) { if (auto root = GetAggregationRoot()) { if (aggregationInfo[aggregationSize + 1] == nullptr) { return; } else { aggregationInfo[aggregationSize + 1] = nullptr; } if (!root->destructing) { destructing = true; delete root; } } } #endif } DescriptableObject::DescriptableObject() :referenceCounter(0) , sharedPtrDestructorProc(0) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA , objectSize(0) , typeDescriptor(0) , destructing(false) , aggregationInfo(nullptr) , aggregationSize(-1) #endif { } #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wexceptions" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wterminate" #endif DescriptableObject::~DescriptableObject() { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA destructing = true; if (IsAggregated()) { if (auto root = GetAggregationRoot()) { if (aggregationInfo[aggregationSize + 1] != nullptr) { #pragma warning (push) #pragma warning (disable: 4297) // Your class should call FinalizeAggregation in the destructor if it inherits from AggregatableDescription. CHECK_ERROR(!IsAggregated(), L"vl::reflection::DescriptableObject::~DescriptableObject0()#FinalizeAggregation function should be called."); #pragma warning (pop) } } for (vint i = 0; i < aggregationSize; i++) { if (auto parent = GetAggregationParent(i)) { if (!parent->destructing) { delete parent; } } } delete[] aggregationInfo; } #endif } #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA description::ITypeDescriptor* DescriptableObject::GetTypeDescriptor() { return typeDescriptor ? *typeDescriptor : 0; } #endif Ptr DescriptableObject::GetInternalProperty(const WString& name) { if (!internalProperties) return 0; vint index = internalProperties->Keys().IndexOf(name); if (index == -1) return 0; return internalProperties->Values().Get(index); } void DescriptableObject::SetInternalProperty(const WString& name, Ptr value) { if (internalProperties) { vint index = internalProperties->Keys().IndexOf(name); if (index == -1) { if (value) { internalProperties->Add(name, value); } } else { if (value) { internalProperties->Set(name, value); } else { internalProperties->Remove(name); if (internalProperties->Count() == 0) { internalProperties = 0; } } } } else { if (value) { internalProperties = Ptr(new InternalPropertyMap); internalProperties->Add(name, value); } } } bool DescriptableObject::Dispose(bool forceDisposing) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (IsAggregated()) { if (auto root = GetAggregationRoot()) { return root->Dispose(forceDisposing); } } #endif if (referenceCounter > 0 && forceDisposing) { throw description::ValueNotDisposableException(); } if (sharedPtrDestructorProc) { return sharedPtrDestructorProc(this, forceDisposing); } else { delete this; return true; } } #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA DescriptableObject* DescriptableObject::SafeGetAggregationRoot() { if (IsAggregated()) { if (auto root = GetAggregationRoot()) { return root; } } return this; } #endif } } /*********************************************************************** .\DESCRIPTABLEVALUE.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace collections; namespace reflection { /*********************************************************************** description::Value ***********************************************************************/ namespace description { Value::Value(DescriptableObject* value) :valueType(value ? RawPtr :Null) ,rawPtr(nullptr) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ,typeDescriptor(nullptr) #endif { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (value) { rawPtr = value->SafeGetAggregationRoot(); } #else rawPtr = value; #endif } Value::Value(Ptr value) :valueType(value ? SharedPtr : Null) ,rawPtr(nullptr) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ,typeDescriptor(nullptr) #endif { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (value) { rawPtr = value->SafeGetAggregationRoot(); sharedPtr = Ptr(rawPtr); } #else rawPtr = value.Obj(); sharedPtr = value; #endif } Value::Value(Ptr value, ITypeDescriptor* associatedTypeDescriptor) :valueType(value ? BoxedValue : Null) , rawPtr(nullptr) , boxedValue(value) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA , typeDescriptor(associatedTypeDescriptor) #endif { } Value::Value() :valueType(Null) ,rawPtr(0) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ,typeDescriptor(nullptr) #endif { } Value::Value(const Value& value) :valueType(value.valueType) ,rawPtr(value.rawPtr) ,sharedPtr(value.sharedPtr) ,boxedValue(value.boxedValue ? value.boxedValue->Copy() : nullptr) #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ,typeDescriptor(value.typeDescriptor) #endif { } Value& Value::operator=(const Value& value) { valueType = value.valueType; rawPtr = value.rawPtr; sharedPtr = value.sharedPtr; boxedValue = value.boxedValue ? value.boxedValue->Copy() : nullptr; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA typeDescriptor = value.typeDescriptor; #endif return *this; } Value::ValueType Value::GetValueType()const { return valueType; } DescriptableObject* Value::GetRawPtr()const { return rawPtr; } Ptr Value::GetSharedPtr()const { return sharedPtr; } Ptr Value::GetBoxedValue()const { return boxedValue; } bool Value::IsNull()const { return valueType == Null; } #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ITypeDescriptor* Value::GetTypeDescriptor()const { switch(valueType) { case RawPtr: case SharedPtr: return rawPtr?rawPtr->GetTypeDescriptor():0; case BoxedValue: return typeDescriptor; default:; } return 0; } WString Value::GetTypeFriendlyName()const { switch(valueType) { case RawPtr: return GetTypeDescriptor()->GetTypeName()+L"*"; case SharedPtr: return L"Ptr<"+GetTypeDescriptor()->GetTypeName()+L">"; case BoxedValue: return GetTypeDescriptor()->GetTypeName(); default: return L"null"; } } bool Value::CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const { if(targetType==GetGlobalTypeManager()->GetRootType()) { return true; } switch(valueType) { case Null: return targetValueType != BoxedValue; case RawPtr: case SharedPtr: if (targetValueType != RawPtr && targetValueType != SharedPtr) return false; break; case BoxedValue: return targetValueType == BoxedValue; } return GetTypeDescriptor()->CanConvertTo(targetType); } bool Value::CanConvertTo(ITypeInfo* targetType)const { if(valueType==Null && targetType->GetDecorator()==ITypeInfo::Nullable) { return true; } ValueType targetValueType=ValueType::Null; { ITypeInfo* currentType=targetType; while(currentType) { switch(targetType->GetDecorator()) { case ITypeInfo::RawPtr: targetValueType=RawPtr; currentType=0; break; case ITypeInfo::SharedPtr: targetValueType=SharedPtr; currentType=0; break; case ITypeInfo::TypeDescriptor: case ITypeInfo::Nullable: targetValueType=BoxedValue; currentType=0; break; default: currentType=currentType->GetElementType(); } } } return CanConvertTo(targetType->GetTypeDescriptor(), targetValueType); } #endif Value Value::From(DescriptableObject* value) { return Value(value); } Value Value::From(Ptr value) { return Value(value); } Value Value::From(Ptr value, ITypeDescriptor* type) { return Value(value, type); } #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA IMethodInfo* Value::SelectMethod(IMethodGroupInfo* methodGroup, collections::Array& arguments) { if(methodGroup->GetMethodCount()==1) { return methodGroup->GetMethod(0); } List methods; for(vint i=0;iGetMethodCount();i++) { IMethodInfo* method=methodGroup->GetMethod(i); if(method->GetParameterCount()==arguments.Count()) { methods.Add(method); } } if(methods.Count()==0) { throw ArgumentCountMismtatchException(methodGroup); } else if(methods.Count()==1) { return methods[0]; } else { // TODO: (enumerable) foreach for(vint i=0;iCheckArguments(arguments); return method; } catch(const TypeDescriptorException&) { } } return methods[0]; } } Value Value::Create(ITypeDescriptor* type) { Array arguments; return Create(type, arguments); } Value Value::Create(ITypeDescriptor* type, collections::Array& arguments) { IMethodGroupInfo* methodGroup=type->GetConstructorGroup(); if(!methodGroup) throw ConstructorNotExistsException(type); IMethodInfo* method=SelectMethod(methodGroup, arguments); return method->Invoke(Value(), arguments); } Value Value::Create(const WString& typeName) { Array arguments; return Create(typeName, arguments); } Value Value::Create(const WString& typeName, collections::Array& arguments) { ITypeDescriptor* type = vl::reflection::description::GetTypeDescriptor(typeName); if(!type) throw TypeNotExistsException(typeName); return Create(type, arguments); } Value Value::InvokeStatic(const WString& typeName, const WString& name) { Array arguments; return InvokeStatic(typeName, name, arguments); } Value Value::InvokeStatic(const WString& typeName, const WString& name, collections::Array& arguments) { ITypeDescriptor* type=vl::reflection::description::GetTypeDescriptor(typeName); if(!type) throw TypeNotExistsException(typeName); IMethodGroupInfo* methodGroup=type->GetMethodGroupByName(name, true); if(!methodGroup) throw MemberNotExistsException(name, type); IMethodInfo* method=SelectMethod(methodGroup, arguments); return method->Invoke(Value(), arguments); } Value Value::GetProperty(const WString& name)const { ITypeDescriptor* type=GetTypeDescriptor(); if(!type) throw ArgumentNullException(L"thisObject", name); IPropertyInfo* prop=type->GetPropertyByName(name, true); if(!prop) throw MemberNotExistsException(name, type); return prop->GetValue(*this); } void Value::SetProperty(const WString& name, const Value& newValue) { ITypeDescriptor* type=GetTypeDescriptor(); if(!type) throw ArgumentNullException(L"thisObject", name); IPropertyInfo* prop=type->GetPropertyByName(name, true); if(!prop) throw MemberNotExistsException(name, type); prop->SetValue(*this, newValue); } Value Value::Invoke(const WString& name)const { Array arguments; return Invoke(name, arguments); } Value Value::Invoke(const WString& name, collections::Array& arguments)const { ITypeDescriptor* type=GetTypeDescriptor(); if(!type) throw ArgumentNullException(L"thisObject", name); IMethodGroupInfo* methodGroup=type->GetMethodGroupByName(name, true); if(!methodGroup) throw MemberNotExistsException(name, type); IMethodInfo* method=SelectMethod(methodGroup, arguments); return method->Invoke(*this, arguments); } Ptr Value::AttachEvent(const WString& name, const Value& function)const { ITypeDescriptor* type=GetTypeDescriptor(); if(!type) throw ArgumentNullException(L"thisObject", name); IEventInfo* eventInfo=type->GetEventByName(name, true); if(!eventInfo) throw MemberNotExistsException(name, type); Ptr proxy=UnboxValue>(function, description::GetTypeDescriptor(), L"function"); return eventInfo->Attach(*this, proxy); } bool Value::DetachEvent(const WString& name, Ptr handler)const { ITypeDescriptor* type = GetTypeDescriptor(); if (!type) throw ArgumentNullException(L"thisObject", name); IEventInfo* eventInfo = type->GetEventByName(name, true); if (!eventInfo) throw MemberNotExistsException(name, type); return eventInfo->Detach(*this, handler); } #endif bool Value::DeleteRawPtr() { if(valueType!=RawPtr) return false; if(!rawPtr) return false; rawPtr->Dispose(true); *this=Value(); return true; } } } } /*********************************************************************** .\DESCRIPTABLEVALUE_COMPARISON.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace collections; namespace reflection { /*********************************************************************** description::Value ***********************************************************************/ namespace description { namespace pbt_selector { template struct UnboxTypeBase { using Type = T; }; template struct ExpectedUnboxType; template struct RealUnboxType; constexpr vint PBT_MIN = (vint)PredefinedBoxableType::PBT_S8; constexpr vint PBT_MAX = (vint)PredefinedBoxableType::PBT_F64; constexpr vint PBT_COUNT = PBT_MAX - PBT_MIN + 1; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct ExpectedUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; template<> struct RealUnboxType : UnboxTypeBase {}; #define DEFINE_PBT_COMPARE(TYPE1, TYPE2)\ inline std::partial_ordering Compare(TYPE1& v1, TYPE2& v2)\ {\ return v1 <=> v2;\ }\ DEFINE_PBT_COMPARE(vint64_t, vint64_t) DEFINE_PBT_COMPARE(vuint64_t, vuint64_t) DEFINE_PBT_COMPARE(double, double) DEFINE_PBT_COMPARE(vint64_t, double) DEFINE_PBT_COMPARE(vuint64_t, double) DEFINE_PBT_COMPARE(double, vint64_t) DEFINE_PBT_COMPARE(double, vuint64_t) inline std::partial_ordering Compare(vint64_t& v1, vuint64_t& v2) { if (v2 > _I64_MAX) return std::partial_ordering::less; return v1 <=> (vint64_t)v2; } inline std::partial_ordering Compare(vuint64_t& v1, vint64_t& v2) { if (v1 > _I64_MAX) return std::partial_ordering::greater; return (vint64_t)v1 <=> v2; } template std::partial_ordering PBT_Compare(const Value& v1, const Value& v2) { using E1 = typename ExpectedUnboxType::Type; using E2 = typename ExpectedUnboxType::Type; using R1 = typename RealUnboxType::Type; using R2 = typename RealUnboxType::Type; E1 e1 = (E1)v1.GetBoxedValue().Cast>()->value; E2 e2 = (E2)v2.GetBoxedValue().Cast>()->value; return Compare(e1, e2); } #undef DEFINE_PBT_COMPARE } std::partial_ordering operator<=>(const Value& a, const Value& b) { auto avt = a.GetValueType(); auto bvt = b.GetValueType(); if (avt == Value::RawPtr || avt == Value::SharedPtr) { if (bvt == Value::RawPtr || bvt == Value::SharedPtr) { auto pa = a.GetRawPtr(); auto pb = b.GetRawPtr(); return pa <=> pb; } } if (avt != bvt) { return avt <=> bvt; } if (avt == Value::BoxedValue) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA auto adt = a.GetTypeDescriptor(); auto bdt = b.GetTypeDescriptor(); if (adt == bdt) #endif { auto pa = a.GetBoxedValue(); auto pb = b.GetBoxedValue(); switch (pa->ComparePrimitive(pb)) { case IBoxedValue::Smaller: return std::partial_ordering::less; case IBoxedValue::Greater: return std::partial_ordering::greater; case IBoxedValue::Equal: return std::partial_ordering::equivalent; default: return std::partial_ordering::unordered; } } #define DEFINE_PBT_MATRIX2(PBT1, PBT2) &pbt_selector::PBT_Compare<(PredefinedBoxableType)PBT1, (PredefinedBoxableType)PBT2> #define DEFINE_PBT_MATRIX1(PBT1)\ DEFINE_PBT_MATRIX2(PBT1, 0),\ DEFINE_PBT_MATRIX2(PBT1, 1),\ DEFINE_PBT_MATRIX2(PBT1, 2),\ DEFINE_PBT_MATRIX2(PBT1, 3),\ DEFINE_PBT_MATRIX2(PBT1, 4),\ DEFINE_PBT_MATRIX2(PBT1, 5),\ DEFINE_PBT_MATRIX2(PBT1, 6),\ DEFINE_PBT_MATRIX2(PBT1, 7),\ DEFINE_PBT_MATRIX2(PBT1, 8),\ DEFINE_PBT_MATRIX2(PBT1, 9) #define DEFINE_PBT_MATRIX\ DEFINE_PBT_MATRIX1(0),\ DEFINE_PBT_MATRIX1(1),\ DEFINE_PBT_MATRIX1(2),\ DEFINE_PBT_MATRIX1(3),\ DEFINE_PBT_MATRIX1(4),\ DEFINE_PBT_MATRIX1(5),\ DEFINE_PBT_MATRIX1(6),\ DEFINE_PBT_MATRIX1(7),\ DEFINE_PBT_MATRIX1(8),\ DEFINE_PBT_MATRIX1(9) { static std::partial_ordering(*PBT_CompareMatrix[pbt_selector::PBT_COUNT][pbt_selector::PBT_COUNT])(const Value & v1, const Value & v2) = { DEFINE_PBT_MATRIX }; auto apbt = (vint)a.GetBoxedValue()->GetBoxableType(); auto bpbt = (vint)b.GetBoxedValue()->GetBoxableType(); if (pbt_selector::PBT_MIN <= apbt && apbt <= pbt_selector::PBT_MAX) { if (pbt_selector::PBT_MIN <= bpbt && bpbt <= pbt_selector::PBT_MAX) { return PBT_CompareMatrix[apbt][bpbt](a, b); } } } #undef DEFINE_PBT_MATRIX #undef DEFINE_PBT_MATRIX1 #undef DEFINE_PBT_MATRI2 return std::partial_ordering::unordered; } return std::partial_ordering::equivalent; } } } } /*********************************************************************** .\METADATA\METADATA.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace collections; namespace reflection { namespace description { #ifndef VCZH_DEBUG_NO_REFLECTION /*********************************************************************** TypeDescriptorTypeInfo ***********************************************************************/ TypeDescriptorTypeInfo::TypeDescriptorTypeInfo(ITypeDescriptor* _typeDescriptor, TypeInfoHint _hint) :typeDescriptor(_typeDescriptor) , hint(_hint) { } TypeDescriptorTypeInfo::~TypeDescriptorTypeInfo() { } ITypeInfo::Decorator TypeDescriptorTypeInfo::GetDecorator() { return ITypeInfo::TypeDescriptor; } TypeInfoHint TypeDescriptorTypeInfo::GetHint() { return hint; } ITypeInfo* TypeDescriptorTypeInfo::GetElementType() { return nullptr; } ITypeDescriptor* TypeDescriptorTypeInfo::GetTypeDescriptor() { return typeDescriptor; } vint TypeDescriptorTypeInfo::GetGenericArgumentCount() { return 0; } ITypeInfo* TypeDescriptorTypeInfo::GetGenericArgument(vint index) { return nullptr; } WString TypeDescriptorTypeInfo::GetTypeFriendlyName() { return typeDescriptor->GetTypeName(); } /*********************************************************************** DecoratedTypeInfo ***********************************************************************/ DecoratedTypeInfo::DecoratedTypeInfo(Ptr _elementType) :elementType(_elementType) { } DecoratedTypeInfo::~DecoratedTypeInfo() { } TypeInfoHint DecoratedTypeInfo::GetHint() { return elementType->GetHint(); } ITypeInfo* DecoratedTypeInfo::GetElementType() { return elementType.Obj(); } ITypeDescriptor* DecoratedTypeInfo::GetTypeDescriptor() { return elementType->GetTypeDescriptor(); } vint DecoratedTypeInfo::GetGenericArgumentCount() { return 0; } ITypeInfo* DecoratedTypeInfo::GetGenericArgument(vint index) { return nullptr; } /*********************************************************************** RawPtrTypeInfo ***********************************************************************/ RawPtrTypeInfo::RawPtrTypeInfo(Ptr _elementType) :DecoratedTypeInfo(_elementType) { } RawPtrTypeInfo::~RawPtrTypeInfo() { } ITypeInfo::Decorator RawPtrTypeInfo::GetDecorator() { return ITypeInfo::RawPtr; } WString RawPtrTypeInfo::GetTypeFriendlyName() { return elementType->GetTypeFriendlyName() + L"*"; } /*********************************************************************** SharedPtrTypeInfo ***********************************************************************/ SharedPtrTypeInfo::SharedPtrTypeInfo(Ptr _elementType) :DecoratedTypeInfo(_elementType) { } SharedPtrTypeInfo::~SharedPtrTypeInfo() { } ITypeInfo::Decorator SharedPtrTypeInfo::GetDecorator() { return ITypeInfo::SharedPtr; } WString SharedPtrTypeInfo::GetTypeFriendlyName() { return elementType->GetTypeFriendlyName() + L"^"; } /*********************************************************************** NullableTypeInfo ***********************************************************************/ NullableTypeInfo::NullableTypeInfo(Ptr _elementType) :DecoratedTypeInfo(_elementType) { } NullableTypeInfo::~NullableTypeInfo() { } ITypeInfo::Decorator NullableTypeInfo::GetDecorator() { return ITypeInfo::Nullable; } WString NullableTypeInfo::GetTypeFriendlyName() { return elementType->GetTypeFriendlyName() + L"?"; } /*********************************************************************** GenericTypeInfo ***********************************************************************/ GenericTypeInfo::GenericTypeInfo(Ptr _elementType) :DecoratedTypeInfo(_elementType) { } GenericTypeInfo::~GenericTypeInfo() { } ITypeInfo::Decorator GenericTypeInfo::GetDecorator() { return ITypeInfo::Generic; } vint GenericTypeInfo::GetGenericArgumentCount() { return genericArguments.Count(); } ITypeInfo* GenericTypeInfo::GetGenericArgument(vint index) { return genericArguments[index].Obj(); } WString GenericTypeInfo::GetTypeFriendlyName() { WString result = elementType->GetTypeFriendlyName() + L"<"; for (auto [type, i] : indexed(genericArguments)) { if (i>0) result += L", "; result += type->GetTypeFriendlyName(); } result += L">"; return result; } void GenericTypeInfo::AddGenericArgument(Ptr value) { genericArguments.Add(value); } #endif #ifndef VCZH_DEBUG_NO_REFLECTION /*********************************************************************** TypeDescriptorImplBase ***********************************************************************/ const WString& TypeDescriptorImplBase::GetFullName() { return cppFullTypeName; } const TypeInfoContent* TypeDescriptorImplBase::GetTypeInfoContentInternal() { return typeInfoContent; } TypeDescriptorImplBase::TypeDescriptorImplBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent) :typeDescriptorFlags(_typeDescriptorFlags) , typeInfoContent(_typeInfoContent) , typeName(WString::Unmanaged(_typeInfoContent->typeName)) { switch (typeInfoContent->cppName) { case TypeInfoContent::VlppType: break; case TypeInfoContent::CppType: cppFullTypeName = WString::Unmanaged(typeInfoContent->typeName); break; case TypeInfoContent::Renamed: cppFullTypeName = WString::Unmanaged(typeInfoContent->cppFullTypeName); break; } } TypeDescriptorImplBase::~TypeDescriptorImplBase() { } ITypeDescriptor::ICpp* TypeDescriptorImplBase::GetCpp() { return typeInfoContent->cppName == TypeInfoContent::VlppType ? nullptr : this; } TypeDescriptorFlags TypeDescriptorImplBase::GetTypeDescriptorFlags() { return typeDescriptorFlags; } const WString& TypeDescriptorImplBase::GetTypeName() { return typeName; } /*********************************************************************** ValueTypeDescriptorBase ***********************************************************************/ void ValueTypeDescriptorBase::LoadInternal() { } void ValueTypeDescriptorBase::Load() { if (!loaded) { loaded = true; LoadInternal(); } } ValueTypeDescriptorBase::ValueTypeDescriptorBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent) :TypeDescriptorImplBase(_typeDescriptorFlags, _typeInfoContent) , loaded(false) { } ValueTypeDescriptorBase::~ValueTypeDescriptorBase() { } bool ValueTypeDescriptorBase::IsAggregatable() { return false; } IValueType* ValueTypeDescriptorBase::GetValueType() { Load(); return valueType.Obj(); } IEnumType* ValueTypeDescriptorBase::GetEnumType() { Load(); return enumType.Obj(); } ISerializableType* ValueTypeDescriptorBase::GetSerializableType() { Load(); return serializableType.Obj(); } vint ValueTypeDescriptorBase::GetBaseTypeDescriptorCount() { return 0; } ITypeDescriptor* ValueTypeDescriptorBase::GetBaseTypeDescriptor(vint index) { return 0; } bool ValueTypeDescriptorBase::CanConvertTo(ITypeDescriptor* targetType) { return this == targetType; } vint ValueTypeDescriptorBase::GetPropertyCount() { return 0; } IPropertyInfo* ValueTypeDescriptorBase::GetProperty(vint index) { return 0; } bool ValueTypeDescriptorBase::IsPropertyExists(const WString& name, bool inheritable) { return false; } IPropertyInfo* ValueTypeDescriptorBase::GetPropertyByName(const WString& name, bool inheritable) { return 0; } vint ValueTypeDescriptorBase::GetEventCount() { return 0; } IEventInfo* ValueTypeDescriptorBase::GetEvent(vint index) { return 0; } bool ValueTypeDescriptorBase::IsEventExists(const WString& name, bool inheritable) { return false; } IEventInfo* ValueTypeDescriptorBase::GetEventByName(const WString& name, bool inheritable) { return 0; } vint ValueTypeDescriptorBase::GetMethodGroupCount() { return 0; } IMethodGroupInfo* ValueTypeDescriptorBase::GetMethodGroup(vint index) { return 0; } bool ValueTypeDescriptorBase::IsMethodGroupExists(const WString& name, bool inheritable) { return false; } IMethodGroupInfo* ValueTypeDescriptorBase::GetMethodGroupByName(const WString& name, bool inheritable) { return 0; } IMethodGroupInfo* ValueTypeDescriptorBase::GetConstructorGroup() { return 0; } /*********************************************************************** ParameterInfoImpl ***********************************************************************/ ParameterInfoImpl::ParameterInfoImpl(IMethodInfo* _ownerMethod, const WString& _name, Ptr _type) :ownerMethod(_ownerMethod) ,name(_name) ,type(_type) { } ParameterInfoImpl::~ParameterInfoImpl() { } ITypeDescriptor* ParameterInfoImpl::GetOwnerTypeDescriptor() { return ownerMethod->GetOwnerTypeDescriptor(); } const WString& ParameterInfoImpl::GetName() { return name; } ITypeInfo* ParameterInfoImpl::GetType() { return type.Obj(); } IMethodInfo* ParameterInfoImpl::GetOwnerMethod() { return ownerMethod; } /*********************************************************************** MethodInfoImpl ***********************************************************************/ MethodInfoImpl::MethodInfoImpl(IMethodGroupInfo* _ownerMethodGroup, Ptr _return, bool _isStatic) :ownerMethodGroup(_ownerMethodGroup) ,ownerProperty(0) ,returnInfo(_return) ,isStatic(_isStatic) { } MethodInfoImpl::~MethodInfoImpl() { } ITypeDescriptor* MethodInfoImpl::GetOwnerTypeDescriptor() { return ownerMethodGroup->GetOwnerTypeDescriptor(); } IPropertyInfo* MethodInfoImpl::GetOwnerProperty() { return ownerProperty; } const WString& MethodInfoImpl::GetName() { return ownerMethodGroup->GetName(); } IMethodGroupInfo* MethodInfoImpl::GetOwnerMethodGroup() { return ownerMethodGroup; } vint MethodInfoImpl::GetParameterCount() { return parameters.Count(); } IParameterInfo* MethodInfoImpl::GetParameter(vint index) { if(0<=index && index& arguments) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(arguments.Count()!=parameters.Count()) { throw ArgumentCountMismtatchException(ownerMethodGroup); } // TODO: (enumerable) foreach for(vint i=0;iGetType())) { throw ArgumentTypeMismtatchException(parameters[i]->GetName(), parameters[i]->GetType(), arguments[i]); } } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } Value MethodInfoImpl::Invoke(const Value& thisObject, collections::Array& arguments) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { if(!isStatic) { throw ArgumentNullException(L"thisObject", this); } } else if(!thisObject.CanConvertTo(ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr, thisObject); } CheckArguments(arguments); return InvokeInternal(thisObject, arguments); #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } Value MethodInfoImpl::CreateFunctionProxy(const Value& thisObject) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { if(!isStatic) { throw ArgumentNullException(L"thisObject", this); } } else if(!thisObject.CanConvertTo(ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerMethodGroup->GetOwnerTypeDescriptor(), Value::RawPtr, thisObject); } return CreateFunctionProxyInternal(thisObject); #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } bool MethodInfoImpl::AddParameter(Ptr parameter) { // TODO: (enumerable) foreach for(vint i=0;iGetName()==parameter->GetName()) { return false; } } parameters.Add(parameter); return true; } bool MethodInfoImpl::SetOwnerMethodgroup(IMethodGroupInfo* _ownerMethodGroup) { if(ownerMethodGroup) return false; ownerMethodGroup=_ownerMethodGroup; return true; } /*********************************************************************** MethodGroupInfoImpl ***********************************************************************/ MethodGroupInfoImpl::MethodGroupInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name) :ownerTypeDescriptor(_ownerTypeDescriptor) ,name(_name) { } MethodGroupInfoImpl::~MethodGroupInfoImpl() { } ITypeDescriptor* MethodGroupInfoImpl::GetOwnerTypeDescriptor() { return ownerTypeDescriptor; } const WString& MethodGroupInfoImpl::GetName() { return name; } vint MethodGroupInfoImpl::GetMethodCount() { return methods.Count(); } IMethodInfo* MethodGroupInfoImpl::GetMethod(vint index) { if(0<=index && index _method) { methods.Add(_method); return true; } /*********************************************************************** EventInfoImpl ***********************************************************************/ EventInfoImpl::EventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name) :ownerTypeDescriptor(_ownerTypeDescriptor) ,name(_name) { } EventInfoImpl::~EventInfoImpl() { } ITypeDescriptor* EventInfoImpl::GetOwnerTypeDescriptor() { return ownerTypeDescriptor; } ITypeInfo* EventInfoImpl::GetHandlerType() { if(!handlerType) { handlerType=GetHandlerTypeInternal(); } return handlerType.Obj(); } vint EventInfoImpl::GetObservingPropertyCount() { return observingProperties.Count(); } IPropertyInfo* EventInfoImpl::GetObservingProperty(vint index) { return observingProperties[index]; } const WString& EventInfoImpl::GetName() { return name; } Ptr EventInfoImpl::Attach(const Value& thisObject, Ptr handler) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { throw ArgumentNullException(L"thisObject", this); } else if(!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject); } DescriptableObject* rawThisObject=thisObject.GetRawPtr(); if(rawThisObject) { return AttachInternal(rawThisObject, handler); } else { return nullptr; } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } bool EventInfoImpl::Detach(const Value& thisObject, Ptr handler) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (thisObject.IsNull()) { throw ArgumentNullException(L"thisObject", this); } else if (!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject); } DescriptableObject* rawThisObject = thisObject.GetRawPtr(); if (rawThisObject) { return DetachInternal(rawThisObject, handler); } else { return false; } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } void EventInfoImpl::Invoke(const Value& thisObject, Ptr arguments) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { throw ArgumentNullException(L"thisObject", this); } else if(!thisObject.CanConvertTo(ownerTypeDescriptor, Value::RawPtr)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, Value::RawPtr, thisObject); } DescriptableObject* rawThisObject=thisObject.GetRawPtr(); if(rawThisObject) { InvokeInternal(rawThisObject, arguments); } else { return; } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } /*********************************************************************** PropertyInfoImpl ***********************************************************************/ PropertyInfoImpl::PropertyInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent) :ownerTypeDescriptor(_ownerTypeDescriptor) ,name(_name) ,getter(_getter) ,setter(_setter) ,valueChangedEvent(_valueChangedEvent) { if(getter) getter->ownerProperty=this; if(setter) setter->ownerProperty=this; if(valueChangedEvent) { valueChangedEvent->observingProperties.Add(this); } } PropertyInfoImpl::~PropertyInfoImpl() { } ITypeDescriptor* PropertyInfoImpl::GetOwnerTypeDescriptor() { return ownerTypeDescriptor; } const WString& PropertyInfoImpl::GetName() { return name; } IPropertyInfo::ICpp* PropertyInfoImpl::GetCpp() { return nullptr; } bool PropertyInfoImpl::IsReadable() { return getter!=0; } bool PropertyInfoImpl::IsWritable() { return setter!=0; } ITypeInfo* PropertyInfoImpl::GetReturn() { return getter?getter->GetReturn():0; } IMethodInfo* PropertyInfoImpl::GetGetter() { return getter; } IMethodInfo* PropertyInfoImpl::GetSetter() { return setter; } IEventInfo* PropertyInfoImpl::GetValueChangedEvent() { return valueChangedEvent; } Value PropertyInfoImpl::GetValue(const Value& thisObject) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(getter) { Array arguments; return getter->Invoke(thisObject, arguments); } else { throw PropertyIsNotReadableException(this); } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } void PropertyInfoImpl::SetValue(Value& thisObject, const Value& newValue) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(setter) { Array arguments(1); arguments[0]=newValue; setter->Invoke(thisObject, arguments); } else { throw PropertyIsNotWritableException(this); } #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } /*********************************************************************** PropertyInfoImpl_StaticCpp ***********************************************************************/ const WString& PropertyInfoImpl_StaticCpp::GetReferenceTemplate() { return referenceTemplate; } PropertyInfoImpl_StaticCpp::PropertyInfoImpl_StaticCpp(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent, const WString& _referenceTemplate) :PropertyInfoImpl(_ownerTypeDescriptor, _name, _getter, _setter, _valueChangedEvent) , referenceTemplate(_referenceTemplate) { } PropertyInfoImpl_StaticCpp::~PropertyInfoImpl_StaticCpp() { } IPropertyInfo::ICpp* PropertyInfoImpl_StaticCpp::GetCpp() { return this; } /*********************************************************************** FieldInfoImpl ***********************************************************************/ FieldInfoImpl::FieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Ptr _returnInfo) :ownerTypeDescriptor(_ownerTypeDescriptor) ,name(_name) ,returnInfo(_returnInfo) { } FieldInfoImpl::~FieldInfoImpl() { } ITypeDescriptor* FieldInfoImpl::GetOwnerTypeDescriptor() { return ownerTypeDescriptor; } const WString& FieldInfoImpl::GetName() { return name; } bool FieldInfoImpl::IsReadable() { return true; } bool FieldInfoImpl::IsWritable() { return true; } ITypeInfo* FieldInfoImpl::GetReturn() { return returnInfo.Obj(); } IMethodInfo* FieldInfoImpl::GetGetter() { return 0; } IMethodInfo* FieldInfoImpl::GetSetter() { return 0; } IEventInfo* FieldInfoImpl::GetValueChangedEvent() { return 0; } Value FieldInfoImpl::GetValue(const Value& thisObject) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { throw ArgumentNullException(L"thisObject", this); } else { auto td = thisObject.GetTypeDescriptor(); auto valueType = td->GetValueType() ? Value::BoxedValue : Value::RawPtr; if(!thisObject.CanConvertTo(ownerTypeDescriptor, valueType)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, valueType, thisObject); } } return GetValueInternal(thisObject); #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } void FieldInfoImpl::SetValue(Value& thisObject, const Value& newValue) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(thisObject.IsNull()) { throw ArgumentNullException(L"thisObject", this); } else { auto td = thisObject.GetTypeDescriptor(); auto valueType = td->GetValueType() ? Value::BoxedValue : Value::RawPtr; if(!thisObject.CanConvertTo(ownerTypeDescriptor, valueType)) { throw ArgumentTypeMismtatchException(L"thisObject", ownerTypeDescriptor, valueType, thisObject); } } if(!newValue.CanConvertTo(returnInfo.Obj())) { throw ArgumentTypeMismtatchException(L"newValue", returnInfo.Obj(), newValue); } SetValueInternal(thisObject, newValue); #else CHECK_FAIL(L"Not Implemented under VCZH_DEBUG_METAONLY_REFLECTION!"); #endif } /*********************************************************************** TypeDescriptorImpl ***********************************************************************/ MethodGroupInfoImpl* TypeDescriptorImpl::PrepareMethodGroup(const WString& name) { vint index=methodGroups.Keys().IndexOf(name); if(index==-1) { auto methodGroup=Ptr(new MethodGroupInfoImpl(this, name)); methodGroups.Add(name, methodGroup); return methodGroup.Obj(); } else { return methodGroups.Values().Get(index).Obj(); } } MethodGroupInfoImpl* TypeDescriptorImpl::PrepareConstructorGroup() { if(!constructorGroup) { constructorGroup=Ptr(new MethodGroupInfoImpl(this, L"")); } return constructorGroup.Obj(); } IPropertyInfo* TypeDescriptorImpl::AddProperty(Ptr value) { properties.Add(value->GetName(), value); return value.Obj(); } IEventInfo* TypeDescriptorImpl::AddEvent(Ptr value) { events.Add(value->GetName(), value); return value.Obj(); } IMethodInfo* TypeDescriptorImpl::AddMethod(const WString& name, Ptr value) { MethodGroupInfoImpl* methodGroup=PrepareMethodGroup(name); value->SetOwnerMethodgroup(methodGroup); methodGroup->AddMethod(value); return value.Obj(); } IMethodInfo* TypeDescriptorImpl::AddConstructor(Ptr value) { MethodGroupInfoImpl* methodGroup=PrepareConstructorGroup(); value->SetOwnerMethodgroup(methodGroup); methodGroup->AddMethod(value); return value.Obj(); } void TypeDescriptorImpl::AddBaseType(ITypeDescriptor* value) { baseTypeDescriptors.Add(value); } void TypeDescriptorImpl::Load() { if(!loaded) { loaded=true; LoadInternal(); } } TypeDescriptorImpl::TypeDescriptorImpl(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent) :TypeDescriptorImplBase(_typeDescriptorFlags, _typeInfoContent) ,loaded(false) { } TypeDescriptorImpl::~TypeDescriptorImpl() { } bool TypeDescriptorImpl::IsAggregatable() { return false; } IValueType* TypeDescriptorImpl::GetValueType() { return nullptr; } IEnumType* TypeDescriptorImpl::GetEnumType() { return nullptr; } ISerializableType* TypeDescriptorImpl::GetSerializableType() { return nullptr; } vint TypeDescriptorImpl::GetBaseTypeDescriptorCount() { Load(); return baseTypeDescriptors.Count(); } ITypeDescriptor* TypeDescriptorImpl::GetBaseTypeDescriptor(vint index) { Load(); if(0<=index && indexCanConvertTo(targetType)) return true; } return false; } vint TypeDescriptorImpl::GetPropertyCount() { Load(); return properties.Count(); } IPropertyInfo* TypeDescriptorImpl::GetProperty(vint index) { Load(); if(0<=index && indexIsPropertyExists(name, true)) { return true; } } } return false; } IPropertyInfo* TypeDescriptorImpl::GetPropertyByName(const WString& name, bool inheritable) { Load(); vint index=properties.Keys().IndexOf(name); if(index!=-1) { return properties.Values().Get(index).Obj(); } if(inheritable) { // TODO: (enumerable) foreach for(vint i=0;iGetPropertyByName(name, true); if(result) { return result; } } } return 0; } vint TypeDescriptorImpl::GetEventCount() { Load(); return events.Count(); } IEventInfo* TypeDescriptorImpl::GetEvent(vint index) { Load(); if(0<=index && indexIsEventExists(name, true)) { return true; } } } return false; } IEventInfo* TypeDescriptorImpl::GetEventByName(const WString& name, bool inheritable) { Load(); vint index=events.Keys().IndexOf(name); if(index!=-1) { return events.Values().Get(index).Obj(); } if(inheritable) { // TODO: (enumerable) foreach for(vint i=0;iGetEventByName(name, true); if(result) { return result; } } } return 0; } vint TypeDescriptorImpl::GetMethodGroupCount() { Load(); return methodGroups.Count(); } IMethodGroupInfo* TypeDescriptorImpl::GetMethodGroup(vint index) { Load(); if(0<=index && indexIsMethodGroupExists(name, true)) { return true; } } } return false; } IMethodGroupInfo* TypeDescriptorImpl::GetMethodGroupByName(const WString& name, bool inheritable) { Load(); vint index=methodGroups.Keys().IndexOf(name); if(index!=-1) { return methodGroups.Values().Get(index).Obj(); } if(inheritable) { // TODO: (enumerable) foreach for(vint i=0;iGetMethodGroupByName(name, true); if(result) { return result; } } } return 0; } IMethodGroupInfo* TypeDescriptorImpl::GetConstructorGroup() { Load(); return constructorGroup.Obj(); } #endif } } } /*********************************************************************** .\PREDEFINED\PREDEFINEDTYPES.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace collections; namespace reflection { namespace description { /*********************************************************************** IValueEnumerable ***********************************************************************/ Ptr IValueEnumerable::Create(collections::LazyList values) { Ptr> enumerable(new LazyList(values)); return Ptr(new ValueEnumerableWrapper>>(enumerable)); } /*********************************************************************** IValueArray ***********************************************************************/ Ptr IValueArray::Create() { return Create(LazyList()); } Ptr IValueArray::Create(Ptr values) { return Create(GetLazyList(values)); } Ptr IValueArray::Create(collections::LazyList values) { auto list = Ptr(new Array); CopyFrom(*list.Obj(), values); return Ptr(new ValueArrayWrapper>>(list)); } /*********************************************************************** IValueList ***********************************************************************/ Ptr IValueList::Create() { return Create(LazyList()); } Ptr IValueList::Create(Ptr values) { return Create(GetLazyList(values)); } Ptr IValueList::Create(collections::LazyList values) { auto list = Ptr(new List); CopyFrom(*list.Obj(), values); return Ptr(new ValueListWrapper>>(list)); } /*********************************************************************** IObservableList ***********************************************************************/ class ReversedObservableList : public ObservableListBase { protected: void NotifyUpdateInternal(vint start, vint count, vint newCount)override { if (observableList) { observableList->ItemChanged(start, count, newCount); } } public: IValueObservableList* observableList = nullptr; }; Ptr IValueObservableList::Create() { return Create(LazyList()); } Ptr IValueObservableList::Create(Ptr values) { return Create(GetLazyList(values)); } Ptr IValueObservableList::Create(collections::LazyList values) { auto list = Ptr(new ReversedObservableList); CopyFrom(*list.Obj(), values); auto wrapper = Ptr(new ValueObservableListWrapper>(list)); list->observableList = wrapper.Obj(); return wrapper; } /*********************************************************************** IValueDictionary ***********************************************************************/ Ptr IValueDictionary::Create() { auto dictionary = Ptr(new Dictionary); return Ptr(new ValueDictionaryWrapper>>(dictionary)); } Ptr IValueDictionary::Create(Ptr values) { auto dictionary = Ptr(new Dictionary); CopyFrom(*dictionary.Obj(), GetLazyList(values)); return Ptr(new ValueDictionaryWrapper>>(dictionary)); } Ptr IValueDictionary::Create(collections::LazyList> values) { auto dictionary = Ptr(new Dictionary); CopyFrom(*dictionary.Obj(), values); return Ptr(new ValueDictionaryWrapper>>(dictionary)); } /*********************************************************************** IValueException ***********************************************************************/ class DefaultValueException : public Object, public IValueException { protected: WString message; public: DefaultValueException(const WString& _message) :message(_message) { } #pragma push_macro("GetMessage") #if defined GetMessage #undef GetMessage #endif WString GetMessage()override { return message; } #pragma pop_macro("GetMessage") bool GetFatal()override { return false; } Ptr GetCallStack()override { return nullptr; } }; Ptr IValueException::Create(const WString& message) { return Ptr(new DefaultValueException(message)); } } } } /*********************************************************************** .\PREDEFINED\TYPEDVALUESERIALIZERPROVIDER.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ namespace vl { using namespace regex; namespace reflection { namespace description { /*********************************************************************** bool ***********************************************************************/ bool TypedValueSerializerProvider::GetDefaultValue() { return false; } bool TypedValueSerializerProvider::Serialize(const bool& input, WString& output) { output = input ? L"true" : L"false"; return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, bool& output) { output = input == L"true"; return input == L"true" || input == L"false"; } /*********************************************************************** wchar_t ***********************************************************************/ wchar_t TypedValueSerializerProvider::GetDefaultValue() { return 0; } bool TypedValueSerializerProvider::Serialize(const wchar_t& input, WString& output) { output = input ? WString::FromChar(input) : L""; return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, wchar_t& output) { if (input.Length() > 1) return false; output = input.Length() == 0 ? 0 : input[0]; return true; } /*********************************************************************** WString ***********************************************************************/ WString TypedValueSerializerProvider::GetDefaultValue() { return L""; } bool TypedValueSerializerProvider::Serialize(const WString& input, WString& output) { output = input; return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, WString& output) { output = input; return true; } /*********************************************************************** Locale ***********************************************************************/ Locale TypedValueSerializerProvider::GetDefaultValue() { return Locale(); } bool TypedValueSerializerProvider::Serialize(const Locale& input, WString& output) { output = input.GetName(); return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, Locale& output) { output = Locale(input); return true; } /*********************************************************************** DateTime ***********************************************************************/ BEGIN_GLOBAL_STORAGE_CLASS(DateTimeSerializerStorage) Regex* regexDateTime = nullptr; vint _Y, _M, _D, _h, _m, _s, _ms; INITIALIZE_GLOBAL_STORAGE_CLASS regexDateTime = new Regex(L"(/d/d/d/d)-(/d/d)-(/d/d) (/d/d):(/d/d):(/d/d).(/d/d/d)"); _Y = regexDateTime->CaptureNames().IndexOf(L"Y"); _M = regexDateTime->CaptureNames().IndexOf(L"M"); _D = regexDateTime->CaptureNames().IndexOf(L"D"); _h = regexDateTime->CaptureNames().IndexOf(L"h"); _m = regexDateTime->CaptureNames().IndexOf(L"m"); _s = regexDateTime->CaptureNames().IndexOf(L"s"); _ms = regexDateTime->CaptureNames().IndexOf(L"ms"); FINALIZE_GLOBAL_STORAGE_CLASS delete regexDateTime; regexDateTime = nullptr; END_GLOBAL_STORAGE_CLASS(DateTimeSerializerStorage) DateTime TypedValueSerializerProvider::GetDefaultValue() { return DateTime(); } WString FormatDigits(vint number, vint length) { WString result = itow(number); while (result.Length() < length) { result = L"0" + result; } return result; } vint ParseDigits(const WString& text) { const wchar_t* reading = text.Buffer(); while (*reading == '0') reading++; if (!*reading) return 0; return wtoi(WString::Unmanaged(reading)); } bool TypedValueSerializerProvider::Serialize(const DateTime& input, WString& output) { output = FormatDigits(input.year, 4) + L"-" + FormatDigits(input.month, 2) + L"-" + FormatDigits(input.day, 2) + L" " + FormatDigits(input.hour, 2) + L":" + FormatDigits(input.minute, 2) + L":" + FormatDigits(input.second, 2) + L"." + FormatDigits(input.milliseconds, 3); return true; } bool TypedValueSerializerProvider::Deserialize(const WString& input, DateTime& output) { auto& dts = GetDateTimeSerializerStorage(); Ptr match = dts.regexDateTime->Match(input); if (!match) return false; if (!match->Success()) return false; if (match->Result().Start() != 0) return false; if (match->Result().Length() != input.Length()) return false; vint year = ParseDigits(match->Groups()[dts._Y].Get(0).Value()); vint month = ParseDigits(match->Groups()[dts._M].Get(0).Value()); vint day = ParseDigits(match->Groups()[dts._D].Get(0).Value()); vint hour = ParseDigits(match->Groups()[dts._h].Get(0).Value()); vint minute = ParseDigits(match->Groups()[dts._m].Get(0).Value()); vint second = ParseDigits(match->Groups()[dts._s].Get(0).Value()); vint milliseconds = ParseDigits(match->Groups()[dts._ms].Get(0).Value()); output = DateTime::FromDateTime(year, month, day, hour, minute, second, milliseconds); return true; } } } } /*********************************************************************** .\REFLECTION\REFLECTION.CPP ***********************************************************************/ /*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/ #include namespace vl { using namespace collections; namespace reflection { namespace description { /*********************************************************************** TypeName ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION IMPL_TYPE_INFO_RENAME(void, system::Void) IMPL_TYPE_INFO_RENAME(vl::reflection::description::VoidValue, system::Void) IMPL_TYPE_INFO_RENAME(vl::reflection::IDescriptable, system::Interface) IMPL_TYPE_INFO_RENAME(vl::reflection::DescriptableObject, system::ReferenceType) IMPL_TYPE_INFO_RENAME(vl::reflection::description::Value, system::Object) IMPL_TYPE_INFO_RENAME(vl::vuint8_t, system::UInt8) IMPL_TYPE_INFO_RENAME(vl::vuint16_t, system::UInt16) IMPL_TYPE_INFO_RENAME(vl::vuint32_t, system::UInt32) IMPL_TYPE_INFO_RENAME(vl::vuint64_t, system::UInt64) IMPL_TYPE_INFO_RENAME(vl::vint8_t, system::Int8) IMPL_TYPE_INFO_RENAME(vl::vint16_t, system::Int16) IMPL_TYPE_INFO_RENAME(vl::vint32_t, system::Int32) IMPL_TYPE_INFO_RENAME(vl::vint64_t, system::Int64) IMPL_TYPE_INFO_RENAME(float, system::Single) IMPL_TYPE_INFO_RENAME(double, system::Double) IMPL_TYPE_INFO_RENAME(bool, system::Boolean) IMPL_TYPE_INFO_RENAME(wchar_t, system::Char) IMPL_TYPE_INFO_RENAME(vl::WString, system::String) IMPL_TYPE_INFO_RENAME(vl::DateTime, system::DateTime) IMPL_TYPE_INFO_RENAME(vl::Locale, system::Locale) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueEnumerator, system::Enumerator) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueEnumerable, system::Enumerable) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueReadonlyList, system::ReadonlyList) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueArray, system::Array) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueList, system::List) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueObservableList, system::ObservableList) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueReadonlyDictionary, system::ReadonlyDictionary) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueDictionary, system::Dictionary) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueInterfaceProxy, system::InterfaceProxy) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueFunctionProxy, system::Function) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueSubscription, system::Subscription) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueCallStack, system::CallStack) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueException, system::Exception) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IBoxedValue, system::reflection::BoxedValue) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IBoxedValue::CompareResult, system::reflection::ValueType::CompareResult) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IValueType, system::reflection::ValueType) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEnumType, system::reflection::EnumType) IMPL_TYPE_INFO_RENAME(vl::reflection::description::ISerializableType, system::reflection::SerializableType) IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeInfo, system::reflection::TypeInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeInfo::Decorator, system::reflection::TypeInfo::Decorator) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMemberInfo, system::reflection::MemberInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEventHandler, system::reflection::EventHandler) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IEventInfo, system::reflection::EventInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IPropertyInfo, system::reflection::PropertyInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IParameterInfo, system::reflection::ParameterInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMethodInfo, system::reflection::MethodInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::IMethodGroupInfo, system::reflection::MethodGroupInfo) IMPL_TYPE_INFO_RENAME(vl::reflection::description::TypeDescriptorFlags, system::reflection::TypeDescriptorFlags) IMPL_TYPE_INFO_RENAME(vl::reflection::description::ITypeDescriptor, system::reflection::TypeDescriptor) #endif /*********************************************************************** Helper Functions ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION vint ITypeDescriptor_GetTypeDescriptorCount() { return GetGlobalTypeManager()->GetTypeDescriptorCount(); } ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index) { return GetGlobalTypeManager()->GetTypeDescriptor(index); } ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name) { return GetGlobalTypeManager()->GetTypeDescriptor(name); } #else vint ITypeDescriptor_GetTypeDescriptorCount() { return 0; } ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index) { return nullptr; } ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name) { return nullptr; } #endif #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value) { return value.GetTypeDescriptor(); } #else ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value) { return nullptr; } #endif /*********************************************************************** LoadPredefinedTypes ***********************************************************************/ #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA #define _ , template<> struct CustomTypeDescriptorSelector { public: class CustomTypeDescriptorImpl : public TypeDescriptorImpl { public: CustomTypeDescriptorImpl() :TypeDescriptorImpl(TypeDescriptorFlags::Class, &TypeInfo::content) { Description::SetAssociatedTypeDescriptor(this); } ~CustomTypeDescriptorImpl() { Description::SetAssociatedTypeDescriptor(0); } protected: void LoadInternal()override { } }; }; BEGIN_STRUCT_MEMBER_FLAG(VoidValue, TypeDescriptorFlags::Primitive) END_STRUCT_MEMBER(VoidValue) BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(IDescriptable, TypeDescriptorFlags::IDescriptable) END_INTERFACE_MEMBER(IDescriptable) BEGIN_STRUCT_MEMBER(DateTime) valueType = Ptr(new SerializableValueType()); serializableType = Ptr(new SerializableType()); STRUCT_MEMBER(year) STRUCT_MEMBER(month) STRUCT_MEMBER(dayOfWeek) STRUCT_MEMBER(day) STRUCT_MEMBER(hour) STRUCT_MEMBER(minute) STRUCT_MEMBER(second) STRUCT_MEMBER(milliseconds) STRUCT_MEMBER(totalMilliseconds) STRUCT_MEMBER(filetime) END_STRUCT_MEMBER(DateTime) BEGIN_INTERFACE_MEMBER(IValueEnumerator) CLASS_MEMBER_PROPERTY_READONLY_FAST(Current) CLASS_MEMBER_PROPERTY_READONLY_FAST(Index) CLASS_MEMBER_METHOD(Next, NO_PARAMETER) END_INTERFACE_MEMBER(IValueEnumerator) BEGIN_INTERFACE_MEMBER(IValueEnumerable) CLASS_MEMBER_METHOD(CreateEnumerator, NO_PARAMETER) END_INTERFACE_MEMBER(IValueEnumerable) BEGIN_INTERFACE_MEMBER(IValueReadonlyList) CLASS_MEMBER_BASE(IValueEnumerable) CLASS_MEMBER_PROPERTY_READONLY_FAST(Count) CLASS_MEMBER_METHOD(Get, { L"index" }) CLASS_MEMBER_METHOD(Contains, { L"value" }) CLASS_MEMBER_METHOD(IndexOf, { L"value" }) END_INTERFACE_MEMBER(IValueReadonlyList) BEGIN_INTERFACE_MEMBER(IValueArray) CLASS_MEMBER_BASE(IValueReadonlyList) CLASS_MEMBER_EXTERNALCTOR(Ptr(), NO_PARAMETER, vl::reflection::description::IValueArray::Create) CLASS_MEMBER_EXTERNALCTOR(Ptr(Ptr), { L"values" }, vl::reflection::description::IValueArray::Create) CLASS_MEMBER_METHOD(Set, { L"index" _ L"value" }) CLASS_MEMBER_METHOD(Resize, { L"size" }) END_INTERFACE_MEMBER(IValueArray) BEGIN_INTERFACE_MEMBER(IValueList) CLASS_MEMBER_BASE(IValueReadonlyList) CLASS_MEMBER_EXTERNALCTOR(Ptr(), NO_PARAMETER, vl::reflection::description::IValueList::Create) CLASS_MEMBER_EXTERNALCTOR(Ptr(Ptr), { L"values" }, vl::reflection::description::IValueList::Create) CLASS_MEMBER_METHOD(Set, { L"index" _ L"value" }) CLASS_MEMBER_METHOD(Add, { L"value" }) CLASS_MEMBER_METHOD(Insert, { L"index" _ L"value" }) CLASS_MEMBER_METHOD(Remove, { L"value" }) CLASS_MEMBER_METHOD(RemoveAt, { L"index" }) CLASS_MEMBER_METHOD(Clear, NO_PARAMETER) END_INTERFACE_MEMBER(IValueList) BEGIN_INTERFACE_MEMBER(IValueObservableList) CLASS_MEMBER_BASE(IValueList) CLASS_MEMBER_EXTERNALCTOR(Ptr(), NO_PARAMETER, vl::reflection::description::IValueObservableList::Create) CLASS_MEMBER_EXTERNALCTOR(Ptr(Ptr), { L"values" }, vl::reflection::description::IValueObservableList::Create) CLASS_MEMBER_EVENT(ItemChanged) END_INTERFACE_MEMBER(IValueObservableList) BEGIN_INTERFACE_MEMBER(IValueReadonlyDictionary) CLASS_MEMBER_PROPERTY_READONLY_FAST(Keys) CLASS_MEMBER_PROPERTY_READONLY_FAST(Values) CLASS_MEMBER_PROPERTY_READONLY_FAST(Count) CLASS_MEMBER_METHOD(Get, { L"key" }) END_INTERFACE_MEMBER(IValueReadonlyDictionary) BEGIN_INTERFACE_MEMBER(IValueDictionary) CLASS_MEMBER_BASE(IValueReadonlyDictionary) CLASS_MEMBER_EXTERNALCTOR(Ptr(), NO_PARAMETER, vl::reflection::description::IValueDictionary::Create) CLASS_MEMBER_EXTERNALCTOR(Ptr(Ptr), { L"values" }, vl::reflection::description::IValueDictionary::Create) CLASS_MEMBER_METHOD(Set, { L"key" _ L"value" }) CLASS_MEMBER_METHOD(Remove, { L"key" }) CLASS_MEMBER_METHOD(Clear, NO_PARAMETER) END_INTERFACE_MEMBER(IValueDictionary) BEGIN_INTERFACE_MEMBER_NOPROXY(IValueInterfaceProxy) CLASS_MEMBER_METHOD(Invoke, { L"methodInfo" _ L"arguments" }) END_INTERFACE_MEMBER(IValueInterfaceProxy) BEGIN_INTERFACE_MEMBER_NOPROXY(IValueFunctionProxy) CLASS_MEMBER_METHOD(Invoke, { L"arguments" }) END_INTERFACE_MEMBER(IValueFunctionProxy) BEGIN_INTERFACE_MEMBER(IValueSubscription) CLASS_MEMBER_EVENT(ValueChanged) CLASS_MEMBER_METHOD(Open, NO_PARAMETER) CLASS_MEMBER_METHOD(Update, NO_PARAMETER) CLASS_MEMBER_METHOD(Close, NO_PARAMETER) END_CLASS_MEMBER(IValueSubscription) BEGIN_INTERFACE_MEMBER_NOPROXY(IValueCallStack) CLASS_MEMBER_PROPERTY_READONLY_FAST(LocalVariables) CLASS_MEMBER_PROPERTY_READONLY_FAST(LocalArguments) CLASS_MEMBER_PROPERTY_READONLY_FAST(CapturedVariables) CLASS_MEMBER_PROPERTY_READONLY_FAST(GlobalVariables) CLASS_MEMBER_PROPERTY_READONLY_FAST(FunctionName) CLASS_MEMBER_PROPERTY_READONLY_FAST(SourceCodeBeforeCodegen) CLASS_MEMBER_PROPERTY_READONLY_FAST(SourceCodeAfterCodegen) CLASS_MEMBER_PROPERTY_READONLY_FAST(RowBeforeCodegen) CLASS_MEMBER_PROPERTY_READONLY_FAST(RowAfterCodegen) END_INTERFACE_MEMBER(IValueCallStack) BEGIN_INTERFACE_MEMBER_NOPROXY(IValueException) #pragma push_macro("GetMessage") #if defined GetMessage #undef GetMessage #endif CLASS_MEMBER_PROPERTY_READONLY_FAST(Message) #pragma pop_macro("GetMessage") CLASS_MEMBER_PROPERTY_READONLY_FAST(Fatal) CLASS_MEMBER_PROPERTY_READONLY_FAST(CallStack) END_INTERFACE_MEMBER(IValueException) BEGIN_INTERFACE_MEMBER_NOPROXY(IBoxedValue) CLASS_MEMBER_METHOD(Copy, NO_PARAMETER) END_INTERFACE_MEMBER(IBoxedValue) BEGIN_ENUM_ITEM(IBoxedValue::CompareResult) ENUM_ITEM_NAMESPACE(IBoxedValue) ENUM_NAMESPACE_ITEM(Smaller) ENUM_NAMESPACE_ITEM(Greater) ENUM_NAMESPACE_ITEM(Equal) ENUM_NAMESPACE_ITEM(NotComparable) END_ENUM_ITEM(ITypeInfo::Decorator) BEGIN_INTERFACE_MEMBER_NOPROXY(IValueType) CLASS_MEMBER_METHOD(CreateDefault, NO_PARAMETER) END_INTERFACE_MEMBER(IValueType) BEGIN_INTERFACE_MEMBER_NOPROXY(IEnumType) CLASS_MEMBER_METHOD(IsFlagEnum, NO_PARAMETER) CLASS_MEMBER_METHOD(GetItemCount, NO_PARAMETER) CLASS_MEMBER_METHOD(GetItemName, { L"index" }) CLASS_MEMBER_METHOD(GetItemValue, { L"index" }) CLASS_MEMBER_METHOD(IndexOfItem, { L"name" }) CLASS_MEMBER_METHOD(ToEnum, { L"value" }) CLASS_MEMBER_METHOD(FromEnum, { L"value" }) END_INTERFACE_MEMBER(IEnumType) BEGIN_INTERFACE_MEMBER_NOPROXY(ISerializableType) CLASS_MEMBER_METHOD(Serialize, { L"input" _ L"output" }) CLASS_MEMBER_METHOD(Deserialize, { L"input" _ L"output" }) END_INTERFACE_MEMBER(ISerializableType) BEGIN_INTERFACE_MEMBER_NOPROXY(ITypeInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(Decorator) CLASS_MEMBER_PROPERTY_READONLY_FAST(ElementType) CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeDescriptor) CLASS_MEMBER_PROPERTY_READONLY_FAST(GenericArgumentCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeFriendlyName) CLASS_MEMBER_METHOD(GetGenericArgument, { L"index" }) END_INTERFACE_MEMBER(ITypeInfo) BEGIN_ENUM_ITEM(ITypeInfo::Decorator) ENUM_ITEM_NAMESPACE(ITypeInfo) ENUM_NAMESPACE_ITEM(RawPtr) ENUM_NAMESPACE_ITEM(SharedPtr) ENUM_NAMESPACE_ITEM(Nullable) ENUM_NAMESPACE_ITEM(TypeDescriptor) ENUM_NAMESPACE_ITEM(Generic) END_ENUM_ITEM(ITypeInfo::Decorator) BEGIN_INTERFACE_MEMBER_NOPROXY(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerTypeDescriptor) CLASS_MEMBER_PROPERTY_READONLY_FAST(Name) END_INTERFACE_MEMBER(IMemberInfo) BEGIN_INTERFACE_MEMBER_NOPROXY(IEventHandler) CLASS_MEMBER_METHOD(IsAttached, NO_PARAMETER) END_INTERFACE_MEMBER(IEventHandler) BEGIN_INTERFACE_MEMBER_NOPROXY(IEventInfo) CLASS_MEMBER_BASE(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(HandlerType) CLASS_MEMBER_PROPERTY_READONLY_FAST(ObservingPropertyCount) CLASS_MEMBER_METHOD(GetObservingProperty, { L"index" }) CLASS_MEMBER_METHOD(Attach, { L"thisObject" _ L"handler" }) CLASS_MEMBER_METHOD(Invoke, { L"thisObject" _ L"arguments" }) END_INTERFACE_MEMBER(IEventInfo) BEGIN_INTERFACE_MEMBER_NOPROXY(IPropertyInfo) CLASS_MEMBER_BASE(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(Return) CLASS_MEMBER_PROPERTY_READONLY_FAST(Getter) CLASS_MEMBER_PROPERTY_READONLY_FAST(Setter) CLASS_MEMBER_PROPERTY_READONLY_FAST(ValueChangedEvent) CLASS_MEMBER_METHOD(IsReadable, NO_PARAMETER) CLASS_MEMBER_METHOD(IsWritable, NO_PARAMETER) CLASS_MEMBER_METHOD(GetValue, { L"thisObject" }) CLASS_MEMBER_METHOD(SetValue, { L"thisObject" _ L"newValue" }) END_INTERFACE_MEMBER(IPropertyInfo) BEGIN_INTERFACE_MEMBER_NOPROXY(IParameterInfo) CLASS_MEMBER_BASE(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(Type) CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerMethod) END_CLASS_MEMBER(IParameterInfo) BEGIN_INTERFACE_MEMBER_NOPROXY(IMethodInfo) CLASS_MEMBER_BASE(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerMethodGroup) CLASS_MEMBER_PROPERTY_READONLY_FAST(OwnerProperty) CLASS_MEMBER_PROPERTY_READONLY_FAST(ParameterCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(Return) CLASS_MEMBER_METHOD(GetParameter, { L"index" }) CLASS_MEMBER_METHOD(IsStatic, NO_PARAMETER) CLASS_MEMBER_METHOD(CheckArguments, { L"arguments" }) CLASS_MEMBER_METHOD(Invoke, { L"thisObject" _ L"arguments" }) CLASS_MEMBER_BASE(IMemberInfo) END_INTERFACE_MEMBER(IMethodInfo) BEGIN_INTERFACE_MEMBER_NOPROXY(IMethodGroupInfo) CLASS_MEMBER_BASE(IMemberInfo) CLASS_MEMBER_PROPERTY_READONLY_FAST(MethodCount) CLASS_MEMBER_METHOD(GetMethod, { L"index" }) END_INTERFACE_MEMBER(IMethodGroupInfo) BEGIN_ENUM_ITEM_MERGABLE(TypeDescriptorFlags) ENUM_CLASS_ITEM(Undefined) ENUM_CLASS_ITEM(Object) ENUM_CLASS_ITEM(IDescriptable) ENUM_CLASS_ITEM(Class) ENUM_CLASS_ITEM(Interface) ENUM_CLASS_ITEM(Primitive) ENUM_CLASS_ITEM(Struct) ENUM_CLASS_ITEM(FlagEnum) ENUM_CLASS_ITEM(NormalEnum) END_ENUM_ITEM(TypeDescriptorFlags) BEGIN_INTERFACE_MEMBER_NOPROXY(ITypeDescriptor) CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeDescriptorFlags) CLASS_MEMBER_PROPERTY_READONLY_FAST(TypeName) CLASS_MEMBER_PROPERTY_READONLY_FAST(ValueType) CLASS_MEMBER_PROPERTY_READONLY_FAST(EnumType) CLASS_MEMBER_PROPERTY_READONLY_FAST(SerializableType) CLASS_MEMBER_PROPERTY_READONLY_FAST(BaseTypeDescriptorCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(PropertyCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(EventCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(MethodGroupCount) CLASS_MEMBER_PROPERTY_READONLY_FAST(ConstructorGroup) CLASS_MEMBER_METHOD(GetBaseTypeDescriptor, { L"index" }) CLASS_MEMBER_METHOD(CanConvertTo, { L"targetType" }) CLASS_MEMBER_METHOD(GetProperty, { L"index" }) CLASS_MEMBER_METHOD(IsPropertyExists, { L"name" _ L"inheritable" }) CLASS_MEMBER_METHOD(GetPropertyByName, { L"name" _ L"inheritable" }) CLASS_MEMBER_METHOD(GetEvent, { L"index" }) CLASS_MEMBER_METHOD(IsEventExists, { L"name" _ L"inheritable" }) CLASS_MEMBER_METHOD(GetEventByName, { L"name" _ L"inheritable" }) CLASS_MEMBER_METHOD(GetMethodGroup, { L"index" }) CLASS_MEMBER_METHOD(IsMethodGroupExists, { L"name" _ L"inheritable" }) CLASS_MEMBER_METHOD(GetMethodGroupByName, { L"name" _ L"inheritable" }) CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptorCount, NO_PARAMETER, vint(*)(), vl::reflection::description::ITypeDescriptor_GetTypeDescriptorCount) CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"index" }, ITypeDescriptor*(*)(vint), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor) CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"name" }, ITypeDescriptor*(*)(const WString&), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor) CLASS_MEMBER_STATIC_EXTERNALMETHOD(GetTypeDescriptor, { L"value" }, ITypeDescriptor*(*)(const Value&), vl::reflection::description::ITypeDescriptor_GetTypeDescriptor) END_INTERFACE_MEMBER(ITypeDescriptor) #undef _ class PredefinedTypeLoader : public Object, public ITypeLoader { public: void Load(ITypeManager* manager)override { manager->SetTypeDescriptor(TypeInfo::content.typeName, Ptr(new TypedValueTypeDescriptorBase)); #define ADD_PRIMITIVE_TYPE(TYPE) manager->SetTypeDescriptor(TypeInfo::content.typeName, Ptr(new PrimitiveTypeDescriptor())); REFLECTION_PREDEFINED_PRIMITIVE_TYPES(ADD_PRIMITIVE_TYPE) #undef ADD_PRIMITIVE_TYPE REFLECTION_PREDEFINED_COMPLEX_TYPES(ADD_TYPE_INFO, VoidValue) } void Unload(ITypeManager* manager)override { } }; #endif bool LoadPredefinedTypes() { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ITypeManager* manager = GetGlobalTypeManager(); if (manager) { auto loader = Ptr(new PredefinedTypeLoader); return manager->AddTypeLoader(loader); } #endif return false; } } } }