/***********************************************************************
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<WString, Ptr<ITypeDescriptor>>		typeDescriptors;
				List<Ptr<ITypeLoader>>							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<ITypeDescriptor> 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<ITypeLoader> 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<ITypeLoader> 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<Value>();
					}
					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 (attributes)
***********************************************************************/

			WString LogTypeManager_FormatAttribute(IAttributeInfo* info)
			{
				WString result = info->GetAttributeType()->GetTypeName() + L"(";
				for (vint i = 0; i < info->GetAttributeValueCount(); i++)
				{
					if (i > 0) result += L", ";
					auto value = info->GetAttributeValue(i);
					auto valueType = info->GetAttributeValueType(i);
					CHECK_ERROR(valueType != nullptr, L"vl::reflection::description::LogTypeManager_FormatAttribute(IAttributeInfo*)#Failed to resolve the reflected type of an attribute argument.");

					if (valueType == GetTypeDescriptor<ITypeDescriptor>())
					{
						if (value.GetValueType() == Value::Null)
						{
							result += valueType->GetTypeName() + L":null";
						}
						else
						{
							auto rawPtr = value.GetRawPtr();
							auto td = dynamic_cast<ITypeDescriptor*>(rawPtr);
							CHECK_ERROR(td != nullptr, L"vl::reflection::description::LogTypeManager_FormatAttribute(IAttributeInfo*)#ITypeDescriptor* attribute value must point to a valid ITypeDescriptor.");
							result += valueType->GetTypeName() + L":" + td->GetTypeName();
						}
					}
					else
					{
						auto serializableType = valueType->GetSerializableType();
						CHECK_ERROR(serializableType != nullptr, L"vl::reflection::description::LogTypeManager_FormatAttribute(IAttributeInfo*)#Attribute argument must use a serializable reflected type.");

						WString data;
						CHECK_ERROR(serializableType->Serialize(value, data), L"vl::reflection::description::LogTypeManager_FormatAttribute(IAttributeInfo*)#Failed to serialize an attribute argument.");
						result += valueType->GetTypeName() + L":" + data;
					}
				}
				result += L")";
				return result;
			}

			void LogTypeManager_PrintAttributes(stream::TextWriter& writer, IAttributeBag* bag, const WString& prefix)
			{
				for (vint i = 0; i < bag->GetAttributeCount(); i++)
				{
					writer.WriteLine(prefix + L"@" + LogTypeManager_FormatAttribute(bag->GetAttribute(i)));
				}
			}

			void LogTypeManager_PrintParameterAttributes(stream::TextWriter& writer, IMethodInfo* info)
			{
				for (vint i = 0; i < info->GetParameterCount(); i++)
				{
					auto parameter = info->GetParameter(i);
					for (vint j = 0; j < parameter->GetAttributeCount(); j++)
					{
						writer.WriteLine(L"    @(" + parameter->GetName() + L")" + LogTypeManager_FormatAttribute(parameter->GetAttribute(j)));
					}
				}
			}

/***********************************************************************
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)
			{
				LogTypeManager_PrintAttributes(writer, info, L"    ");
				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; j<type->GetPropertyCount(); 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);
					LogTypeManager_PrintAttributes(writer, info, L"    ");
					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)
			{
				LogTypeManager_PrintAttributes(writer, info, L"    ");
				if (auto cpp = info->GetCpp())
				{
					writer.WriteLine(L"    @InvokeTemplate:" + cpp->GetInvokeTemplate());
					writer.WriteLine(L"    @ClosureTemplate:" + cpp->GetClosureTemplate());
				}
				LogTypeManager_PrintParameterAttributes(writer, info);

				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; j<type->GetBaseTypeDescriptorCount(); 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<IValueInterfaceProxy>::content.typeName)
							{
								acceptProxy = true;
								return true;
							}
						}
					}
				}

				if (!containsConstructor)
				{
					if (typeDescriptor->GetTypeName() == TypeInfo<IDescriptable>::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");
					}
					LogTypeManager_PrintAttributes(writer, type, L"");

					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<ITypeDescriptor*, vint>		tdIndex;
				Dictionary<IMethodInfo*, vint>			miIndex;
				Dictionary<IPropertyInfo*, vint>		piIndex;
				Dictionary<IEventInfo*, vint>			eiIndex;
			};

			struct MetaonlyReaderContext
			{
				Dictionary<WString, Ptr<ISerializableType>>		serializableTypes;
				List<Ptr<ITypeDescriptor>>				tds;
				List<Ptr<IMethodInfo>>					mis;
				List<Ptr<IPropertyInfo>>				pis;
				List<Ptr<IEventInfo>>					eis;
				ITypeDescriptor*						itdTd = nullptr;
			};

/***********************************************************************
MetaonlyTypeInfo
***********************************************************************/

			class MetaonlyTypeInfo : public Object, public ITypeInfo
			{
				friend struct stream::internal::Serialization<MetaonlyTypeInfo>;
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Decorator						decorator = TypeDescriptor;
				TypeInfoHint					hint = TypeInfoHint::Normal;
				Ptr<MetaonlyTypeInfo>			elementType;
				vint							typeDecriptor = -1;
				List<Ptr<MetaonlyTypeInfo>>		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<MetaonlyTypeInfo*>(info))
				{
					minfo->SetContext(context);
				}
				return info;
			}

/***********************************************************************
Metadata
***********************************************************************/

			struct IdRange
			{
				vint								start = -1;
				vint								count = 0;
			};

			struct AttributeValueMetadata
			{
				vint								typeDescriptor = -1;
				vint								typeDescriptorValue = -1;
				WString								data;
			};

			struct AttributeInfoMetadata
			{
				vint								attributeType = -1;
				List<Ptr<AttributeValueMetadata>>	values;
			};

			struct ParameterInfoMetadata
			{
				WString								name;
				Ptr<MetaonlyTypeInfo>				type;
				List<Ptr<AttributeInfoMetadata>>	attributes;
			};

			struct MethodInfoMetadata
			{
				WString								invokeTemplate;
				WString								closureTemplate;
				WString								name;
				vint								ownerTypeDescriptor = -1;
				vint								ownerProperty = -1;
				List<Ptr<ParameterInfoMetadata>>	parameters;
				Ptr<MetaonlyTypeInfo>				returnType;
				bool								isStatic = false;
				List<Ptr<AttributeInfoMetadata>>	attributes;
			};

			struct PropertyInfoMetadata
			{
				WString								referenceTemplate;
				WString								name;
				vint								ownerTypeDescriptor = -1;
				bool								isReadable = false;
				bool								isWritable = false;
				Ptr<MetaonlyTypeInfo>				returnType;
				vint								getter = -1;
				vint								setter = -1;
				vint								valueChangedEvent = -1;
				List<Ptr<AttributeInfoMetadata>>	attributes;
			};

			struct EventInfoMetadata
			{
				WString								attachTemplate;
				WString								detachTemplate;
				WString								invokeTemplate;
				WString								name;
				vint								ownerTypeDescriptor = -1;
				Ptr<MetaonlyTypeInfo>				handlerType;
				List<vint>							observingProperties;
				List<Ptr<AttributeInfoMetadata>>	attributes;
			};

			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<WString>						enumItems;
				List<vuint64_t>						enumValues;
				List<vint>							baseTypeDescriptors;
				List<vint>							properties;
				List<vint>							events;
				List<vint>							methods;
				List<IdRange>						methodGroups;
				IdRange								constructorGroup;
				List<Ptr<AttributeInfoMetadata>>	attributes;
			};
		}
	}

	namespace stream
	{
		namespace internal
		{

/***********************************************************************
Serialization
***********************************************************************/

			BEGIN_SERIALIZATION(reflection::description::IdRange)
				SERIALIZE(start)
				SERIALIZE(count)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(reflection::description::AttributeValueMetadata)
				SERIALIZE(typeDescriptor)
				SERIALIZE(typeDescriptorValue)
				SERIALIZE(data)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(reflection::description::AttributeInfoMetadata)
				SERIALIZE(attributeType)
				SERIALIZE(values)
			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)
				SERIALIZE(attributes)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(reflection::description::MethodInfoMetadata)
				SERIALIZE(invokeTemplate)
				SERIALIZE(closureTemplate)
				SERIALIZE(name)
				SERIALIZE(ownerTypeDescriptor)
				SERIALIZE(ownerProperty)
				SERIALIZE(parameters)
				SERIALIZE(returnType)
				SERIALIZE(isStatic)
				SERIALIZE(attributes)
			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)
				SERIALIZE(attributes)
			END_SERIALIZATION

			BEGIN_SERIALIZATION(reflection::description::EventInfoMetadata)
				SERIALIZE(attachTemplate)
				SERIALIZE(detachTemplate)
				SERIALIZE(invokeTemplate)
				SERIALIZE(name)
				SERIALIZE(ownerTypeDescriptor)
				SERIALIZE(handlerType)
				SERIALIZE(observingProperties)
				SERIALIZE(attributes)
			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)
				SERIALIZE(attributes)
			END_SERIALIZATION
		}
	}

	namespace reflection
	{
		namespace description
		{

			using Reader = stream::internal::Reader<Ptr<MetaonlyReaderContext>>;
			using Writer = stream::internal::Writer<Ptr<MetaonlyWriterContext>>;

/***********************************************************************
IMethodInfo
***********************************************************************/

			class MetaonlyParameterInfo : public MemberInfoBase<IParameterInfo>
			{
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Ptr<ParameterInfoMetadata>		metadata;
				vint							ownerTypeDescriptor = -1;
				IMethodInfo*					ownerMethod = nullptr;

			public:
				MetaonlyParameterInfo(MetaonlyReaderContext* _context, Ptr<ParameterInfoMetadata> _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 MemberInfoBase<IMethodInfo>, protected IMethodInfo::ICpp
			{
				friend class MetaonlyMethodGroupInfo;
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Ptr<MethodInfoMetadata>			metadata;
				IMethodGroupInfo*				methodGroup = nullptr;
				List<Ptr<IParameterInfo>>		parameters;

			public:
				MetaonlyMethodInfo(MetaonlyReaderContext* _context, Ptr<MethodInfoMetadata> _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)));
					}
				}

				Ptr<MethodInfoMetadata> GetMetadata()
				{
					return metadata;
				}

				// 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<Value>& arguments) override
				{
					CHECK_FAIL(L"Not Supported!");
				}

				Value Invoke(const Value& thisObject, collections::Array<Value>& 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<TypeDescriptorMetadata>		metadata;
				IdRange							idRange;
			public:
				MetaonlyMethodGroupInfo(MetaonlyReaderContext* _context, Ptr<TypeDescriptorMetadata> _metadata, IdRange _idRange)
					: context(_context)
					, metadata(_metadata)
					, idRange(_idRange)
				{
				}

				// IAttributeBag

				vint GetAttributeCount() override
				{
					return 0;
				}

				IAttributeInfo* GetAttribute(vint index) override
				{
					return nullptr;
				}

				// 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<MetaonlyMethodInfo*>(context->mis[metadata->methods[idRange.start + index]].Obj());
					if (info->methodGroup == nullptr)
					{
						info->methodGroup = this;
					}
					return info;
				}
			};

/***********************************************************************
IPropertyInfo
***********************************************************************/

			class MetaonlyPropertyInfo : public MemberInfoBase<IPropertyInfo>, protected IPropertyInfo::ICpp
			{
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Ptr<PropertyInfoMetadata>		metadata;

			public:
				MetaonlyPropertyInfo(MetaonlyReaderContext* _context, Ptr<PropertyInfoMetadata> _metadata)
					: context(_context)
					, metadata(_metadata)
				{
				}

				Ptr<PropertyInfoMetadata> GetMetadata()
				{
					return 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 MemberInfoBase<IEventInfo>, protected IEventInfo::ICpp
			{
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Ptr<EventInfoMetadata>			metadata;

			public:
				MetaonlyEventInfo(MetaonlyReaderContext* _context, Ptr<EventInfoMetadata> _metadata)
					: context(_context)
					, metadata(_metadata)
				{
				}

				Ptr<EventInfoMetadata> GetMetadata()
				{
					return 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<IEventHandler> Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler) override
				{
					CHECK_FAIL(L"Not Supported!");
				}

				bool Detach(const Value& thisObject, Ptr<IEventHandler> handler) override
				{
					CHECK_FAIL(L"Not Supported!");
				}

				void Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments) override
				{
					CHECK_FAIL(L"Not Supported!");
				}
			};

/***********************************************************************
ITypeDescriptor
***********************************************************************/

			class MetaonlyTypeDescriptor
				: public AttributeBagSource
				, public ITypeDescriptor
				, protected ITypeDescriptor::ICpp
				, protected IValueType
				, protected IEnumType
			{
			protected:
				MetaonlyReaderContext*			context = nullptr;
				Ptr<TypeDescriptorMetadata>		metadata;
				ISerializableType*				serializableType = nullptr;
				List<Ptr<IMethodGroupInfo>>		methodGroups;
				Ptr<IMethodGroupInfo>			constructorGroup;

			public:
				MetaonlyTypeDescriptor(MetaonlyReaderContext* _context, Ptr<TypeDescriptorMetadata> _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));
					}
				}

				Ptr<TypeDescriptorMetadata> GetMetadata()
				{
					return metadata;
				}

				// IAttributeBag

				vint GetAttributeCount() override
				{
					return GetAttributeCountInternal(nullptr);
				}

				IAttributeInfo* GetAttribute(vint index) override
				{
					return GetAttributeInternal(nullptr, index);
				}

				// 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();
				}
			};

/***********************************************************************
Attribute Metadata Helpers
***********************************************************************/

			void GenerateMetaonlyAttributes(MetaonlyWriterContext& context, List<Ptr<AttributeInfoMetadata>>& metadataList, IAttributeBag* attributeBag)
			{
#define ERROR_MESSAGE_PREFIX L"vl::reflection::description::GenerateMetaonlyAttributes(MetaonlyWriterContext&, collections::List<AttributeInfoMetadata>&, IAttributeBag*)#"
				auto itdTd = GetTypeDescriptor<ITypeDescriptor>();
				for (vint i = 0; i < attributeBag->GetAttributeCount(); i++)
				{
					auto info = attributeBag->GetAttribute(i);
					auto attributeMetadata = Ptr(new AttributeInfoMetadata{
						.attributeType = context.tdIndex[info->GetAttributeType()],
					});
					for (vint j = 0; j < info->GetAttributeValueCount(); j++)
					{
						auto value = info->GetAttributeValue(j);
						auto valueType = info->GetAttributeValueType(j);
						CHECK_ERROR(valueType != nullptr, ERROR_MESSAGE_PREFIX L"Failed to resolve the reflected type of an attribute argument.");

						if (valueType == itdTd)
						{
							vint tdValueIndex = -1;
							if (value.GetValueType() != Value::Null)
							{
								auto rawPtr = value.GetRawPtr();
								auto td = dynamic_cast<ITypeDescriptor*>(rawPtr);
								CHECK_ERROR(td != nullptr, ERROR_MESSAGE_PREFIX L"ITypeDescriptor* attribute value must point to a valid ITypeDescriptor.");
								CHECK_ERROR(context.tdIndex.Keys().Contains(td), ERROR_MESSAGE_PREFIX L"ITypeDescriptor* attribute value must point to a registered ITypeDescriptor.");
								tdValueIndex = context.tdIndex[td];
							}
							attributeMetadata->values.Add(Ptr(new AttributeValueMetadata{
								.typeDescriptor = context.tdIndex[valueType],
								.typeDescriptorValue = tdValueIndex,
							}));
						}
						else
						{
							auto serializableType = valueType->GetSerializableType();
							CHECK_ERROR(serializableType != nullptr, ERROR_MESSAGE_PREFIX L"Attribute argument must use a serializable reflected type.");

							WString data;
							CHECK_ERROR(serializableType->Serialize(value, data), ERROR_MESSAGE_PREFIX L"Failed to serialize an attribute argument.");
							attributeMetadata->values.Add(Ptr(new AttributeValueMetadata{
								.typeDescriptor = context.tdIndex[valueType],
								.data = data,
							}));
						}
					}
					metadataList.Add(attributeMetadata);
				}
#undef ERROR_MESSAGE_PREFIX
			}

			void LoadMetaonlyAttributes(
				MetaonlyReaderContext* context,
				AttributeBagSource* source,
				IMemberInfo* memberInfo,
				const List<Ptr<AttributeInfoMetadata>>& attributeMetadataList,
				ITypeDescriptor* itdTd
			)
			{
#define ERROR_MESSAGE_PREFIX L"vl::reflection::description::LoadMetaonlyAttributes(MetaonlyReaderContext*, AttributeBagSource*, IMemberInfo*, const collections::List<AttributeInfoMetadata>&, ITypeDescriptor*)#"
				for (vint i = 0; i < attributeMetadataList.Count(); i++)
				{
					auto&& attributeMetadata = attributeMetadataList[i];
					CHECK_ERROR(0 <= attributeMetadata->attributeType && attributeMetadata->attributeType < context->tds.Count(), ERROR_MESSAGE_PREFIX L"Failed to resolve the reflected attribute type.");
					auto attributeType = context->tds[attributeMetadata->attributeType].Obj();
					auto info = Ptr(new AttributeInfoImpl(attributeType));

					for (vint j = 0; j < attributeMetadata->values.Count(); j++)
					{
						auto&& valueMetadata = attributeMetadata->values[j];
						CHECK_ERROR(0 <= valueMetadata->typeDescriptor && valueMetadata->typeDescriptor < context->tds.Count(), ERROR_MESSAGE_PREFIX L"Failed to resolve the reflected value type of an attribute argument.");
						auto reflectedValueType = context->tds[valueMetadata->typeDescriptor].Obj();

						if (itdTd != nullptr && reflectedValueType == itdTd)
						{
							if (valueMetadata->typeDescriptorValue >= 0)
							{
								CHECK_ERROR(valueMetadata->typeDescriptorValue < context->tds.Count(), ERROR_MESSAGE_PREFIX L"Failed to resolve the ITypeDescriptor* attribute value.");
								auto referencedTd = context->tds[valueMetadata->typeDescriptorValue].Obj();
								auto value = Value::From(dynamic_cast<DescriptableObject*>(referencedTd));
								info->AddValue(reflectedValueType, value);
							}
							else
							{
								info->AddValue(reflectedValueType, Value());
							}
						}
						else
						{
							auto serializableType = reflectedValueType->GetSerializableType();
							CHECK_ERROR(serializableType != nullptr, ERROR_MESSAGE_PREFIX L"Failed to resolve the serializable type of an attribute argument.");

							Value value;
							CHECK_ERROR(serializableType->Deserialize(valueMetadata->data, value), ERROR_MESSAGE_PREFIX L"Failed to deserialize an attribute argument.");
							value = Value::From(value.GetBoxedValue(), reflectedValueType);
							info->AddValue(reflectedValueType, value);
						}
					}

					source->RegisterAttribute(memberInfo, info);
				}
#undef ERROR_MESSAGE_PREFIX
			}

/***********************************************************************
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;
				}

				GenerateMetaonlyAttributes(*writer.context.Obj(), metadata->attributes, td);
				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()));
					GenerateMetaonlyAttributes(*writer.context.Obj(), piMetadata->attributes, pi);
					metadata->parameters.Add(piMetadata);
				}
				metadata->returnType = Ptr(new MetaonlyTypeInfo(*writer.context.Obj(), mi->GetReturn()));
				metadata->isStatic = mi->IsStatic();
				GenerateMetaonlyAttributes(*writer.context.Obj(), metadata->attributes, mi);
				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];
				}
				GenerateMetaonlyAttributes(*writer.context.Obj(), metadata->attributes, pi);
				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)]);
				}
				GenerateMetaonlyAttributes(*writer.context.Obj(), metadata->attributes, ei);
				writer << metadata;
			}

			void GenerateMetaonlyTypes(stream::IStream& outputStream)
			{
				Writer writer(outputStream);
				writer.context = Ptr(new MetaonlyWriterContext);

				Dictionary<WString, ITypeDescriptor*> tds;
				List<IMethodInfo*> mis;
				List<IPropertyInfo*> pis;
				List<IEventInfo*> 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<MetaonlyReaderContext>				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<ITypeLoader> LoadMetaonlyTypes(stream::IStream& inputStream, const collections::Dictionary<WString, Ptr<ISerializableType>>& 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;

					{
						auto itdTypeName = WString::Unmanaged(TypeInfo<ITypeDescriptor>::content.typeName);
						for (vint i = 0; i < tdCount; i++)
						{
							Ptr<TypeDescriptorMetadata> metadata;
							reader << metadata;
							auto td = Ptr(new MetaonlyTypeDescriptor(context.Obj(), metadata));
							if (td->GetTypeName() == itdTypeName)
							{
								context->itdTd = td.Obj();
							}
							context->tds.Add(td);
						}
					}
					for (vint i = 0; i < miCount; i++)
					{
						Ptr<MethodInfoMetadata> metadata;
						reader << metadata;
						context->mis.Add(Ptr(new MetaonlyMethodInfo(context.Obj(), metadata)));
					}
					for (vint i = 0; i < piCount; i++)
					{
						Ptr<PropertyInfoMetadata> metadata;
						reader << metadata;
						context->pis.Add(Ptr(new MetaonlyPropertyInfo(context.Obj(), metadata)));
					}
					for (vint i = 0; i < eiCount; i++)
					{
						Ptr<EventInfoMetadata> metadata;
						reader << metadata;
						context->eis.Add(Ptr(new MetaonlyEventInfo(context.Obj(), metadata)));
					}
				}

#define ERROR_MESSAGE_PREFIX L"vl::reflection::description::LoadMetaonlyTypes(stream::IStream&, const collections::Dictionary<WString, Ptr<ISerializableType>>&)#"
				for (vint i = 0; i < context->tds.Count(); i++)
				{
					auto td = context->tds[i].Obj();
					auto source = dynamic_cast<AttributeBagSource*>(td);
					CHECK_ERROR(source != nullptr, ERROR_MESSAGE_PREFIX L"Metaonly type descriptors must provide attribute storage.");
					auto metadata = dynamic_cast<MetaonlyTypeDescriptor*>(td)->GetMetadata();
					LoadMetaonlyAttributes(context.Obj(), source, nullptr, metadata->attributes, context->itdTd);
				}

				for (vint i = 0; i < context->mis.Count(); i++)
				{
					auto method = context->mis[i].Obj();
					auto source = dynamic_cast<AttributeBagSource*>(method->GetOwnerTypeDescriptor());
					CHECK_ERROR(source != nullptr, ERROR_MESSAGE_PREFIX L"Method owner type descriptors must provide attribute storage.");
					auto metadata = dynamic_cast<MetaonlyMethodInfo*>(method)->GetMetadata();
					LoadMetaonlyAttributes(context.Obj(), source, method, metadata->attributes, context->itdTd);
					for (vint j = 0; j < method->GetParameterCount(); j++)
					{
						LoadMetaonlyAttributes(context.Obj(), source, method->GetParameter(j), metadata->parameters[j]->attributes, context->itdTd);
					}
				}

				for (vint i = 0; i < context->pis.Count(); i++)
				{
					auto property = context->pis[i].Obj();
					auto source = dynamic_cast<AttributeBagSource*>(property->GetOwnerTypeDescriptor());
					CHECK_ERROR(source != nullptr, ERROR_MESSAGE_PREFIX L"Property owner type descriptors must provide attribute storage.");
					auto metadata = dynamic_cast<MetaonlyPropertyInfo*>(property)->GetMetadata();
					LoadMetaonlyAttributes(context.Obj(), source, property, metadata->attributes, context->itdTd);
				}

				for (vint i = 0; i < context->eis.Count(); i++)
				{
					auto eventInfo = context->eis[i].Obj();
					auto source = dynamic_cast<AttributeBagSource*>(eventInfo->GetOwnerTypeDescriptor());
					CHECK_ERROR(source != nullptr, ERROR_MESSAGE_PREFIX L"Event owner type descriptors must provide attribute storage.");
					auto metadata = dynamic_cast<MetaonlyEventInfo*>(eventInfo)->GetMetadata();
					LoadMetaonlyAttributes(context.Obj(), source, eventInfo, metadata->attributes, context->itdTd);
				}
#undef ERROR_MESSAGE_PREFIX

				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<DescriptableObject>& value)
		{
			CHECK_ERROR(IsAggregated(), L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#This function should not be called on non-aggregated objects.");
			CHECK_ERROR(0 <= index && index < aggregationSize, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Index out of range.");
			CHECK_ERROR(aggregationInfo[index] == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#This index has been used.");
			CHECK_ERROR(value, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Parent should not be null");
			CHECK_ERROR(!value->IsAggregated() || value->GetAggregationRoot() == nullptr, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#Parent already has a aggregation root.");
			CHECK_ERROR(value->referenceCounter == 1, L"vl::reflection::DescriptableObject::SetAggregationParent(vint, Ptr<DescriptableObject>&)#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;
						// The old root skips this destructing subtree, so keep its descendants rooted in a live object.
						aggregationInfo[aggregationSize] = nullptr;
						for (vint i = 0; i < aggregationSize; i++)
						{
							if (auto parent = GetAggregationParent(i))
							{
								parent->SetAggregationRoot(this);
							}
						}
						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<T>.
						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<Object> 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<Object> 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<DescriptableObject> 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<IBoxedValue> 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<DescriptableObject> Value::GetSharedPtr()const
			{
				return sharedPtr;
			}

			Ptr<IBoxedValue> 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<DescriptableObject> value)
			{
				return Value(value);
			}

			Value Value::From(Ptr<IBoxedValue> value, ITypeDescriptor* type)
			{
				return Value(value, type);
			}

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

			IMethodInfo* Value::SelectMethod(IMethodGroupInfo* methodGroup, collections::Array<Value>& arguments)
			{
				if(methodGroup->GetMethodCount()==1)
				{
					return methodGroup->GetMethod(0);
				}

				List<IMethodInfo*> methods;
				for(vint i=0;i<methodGroup->GetMethodCount();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;i<methods.Count();i++)
					{
						IMethodInfo* method=methods[i];
						try
						{
							method->CheckArguments(arguments);
							return method;
						}
						catch(const TypeDescriptorException&)
						{
						}
					}
					return methods[0];
				}
			}

			Value Value::Create(ITypeDescriptor* type)
			{
				Array<Value> arguments;
				return Create(type, arguments);
			}

			Value Value::Create(ITypeDescriptor* type, collections::Array<Value>& 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<Value> arguments;
				return Create(typeName, arguments);
			}

			Value Value::Create(const WString& typeName, collections::Array<Value>& 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<Value> arguments;
				return InvokeStatic(typeName, name, arguments);
			}

			Value Value::InvokeStatic(const WString& typeName, const WString& name, collections::Array<Value>& 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<Value> arguments;
				return Invoke(name, arguments);
			}

			Value Value::Invoke(const WString& name, collections::Array<Value>& 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<IEventHandler> 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<IValueFunctionProxy> proxy=UnboxValue<Ptr<IValueFunctionProxy>>(function, description::GetTypeDescriptor<IValueFunctionProxy>(), L"function");
				return eventInfo->Attach(*this, proxy);
			}

			bool Value::DetachEvent(const WString& name, Ptr<IEventHandler> 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<typename T>
				struct UnboxTypeBase { using Type = T; };

				template<PredefinedBoxableType> struct ExpectedUnboxType;
				template<PredefinedBoxableType> 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<PredefinedBoxableType::PBT_S8>	: UnboxTypeBase<vint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S16>	: UnboxTypeBase<vint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S32>	: UnboxTypeBase<vint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_S64>	: UnboxTypeBase<vint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U8>	: UnboxTypeBase<vuint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U16>	: UnboxTypeBase<vuint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U32>	: UnboxTypeBase<vuint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_U64>	: UnboxTypeBase<vuint64_t> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_F32>	: UnboxTypeBase<double> {};
				template<> struct ExpectedUnboxType<PredefinedBoxableType::PBT_F64>	: UnboxTypeBase<double> {};

				template<> struct RealUnboxType<PredefinedBoxableType::PBT_S8>	: UnboxTypeBase<vint8_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_S16>	: UnboxTypeBase<vint16_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_S32>	: UnboxTypeBase<vint32_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_S64>	: UnboxTypeBase<vint64_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_U8>	: UnboxTypeBase<vuint8_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_U16>	: UnboxTypeBase<vuint16_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_U32>	: UnboxTypeBase<vuint32_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_U64>	: UnboxTypeBase<vuint64_t> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_F32>	: UnboxTypeBase<float> {};
				template<> struct RealUnboxType<PredefinedBoxableType::PBT_F64>	: UnboxTypeBase<double> {};

#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<PredefinedBoxableType PBT1, PredefinedBoxableType PBT2>
				std::partial_ordering PBT_Compare(const Value& v1, const Value& v2)
				{
					using E1 = typename ExpectedUnboxType<PBT1>::Type;
					using E2 = typename ExpectedUnboxType<PBT2>::Type;
					using R1 = typename RealUnboxType<PBT1>::Type;
					using R2 = typename RealUnboxType<PBT2>::Type;

					E1 e1 = (E1)v1.GetBoxedValue().Cast<IValueType::TypedBox<R1>>()->value;
					E2 e2 = (E2)v2.GetBoxedValue().Cast<IValueType::TypedBox<R2>>()->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<ITypeInfo> _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<ITypeInfo> _elementType)
				:DecoratedTypeInfo(_elementType)
			{
			}

			RawPtrTypeInfo::~RawPtrTypeInfo()
			{
			}

			ITypeInfo::Decorator RawPtrTypeInfo::GetDecorator()
			{
				return ITypeInfo::RawPtr;
			}

			WString RawPtrTypeInfo::GetTypeFriendlyName()
			{
				return elementType->GetTypeFriendlyName() + L"*";
			}

/***********************************************************************
SharedPtrTypeInfo
***********************************************************************/

			SharedPtrTypeInfo::SharedPtrTypeInfo(Ptr<ITypeInfo> _elementType)
				:DecoratedTypeInfo(_elementType)
			{
			}

			SharedPtrTypeInfo::~SharedPtrTypeInfo()
			{
			}

			ITypeInfo::Decorator SharedPtrTypeInfo::GetDecorator()
			{
				return ITypeInfo::SharedPtr;
			}

			WString SharedPtrTypeInfo::GetTypeFriendlyName()
			{
				return elementType->GetTypeFriendlyName() + L"^";
			}

/***********************************************************************
NullableTypeInfo
***********************************************************************/

			NullableTypeInfo::NullableTypeInfo(Ptr<ITypeInfo> _elementType)
				:DecoratedTypeInfo(_elementType)
			{
			}

			NullableTypeInfo::~NullableTypeInfo()
			{
			}

			ITypeInfo::Decorator NullableTypeInfo::GetDecorator()
			{
				return ITypeInfo::Nullable;
			}

			WString NullableTypeInfo::GetTypeFriendlyName()
			{
				return elementType->GetTypeFriendlyName() + L"?";
			}

/***********************************************************************
GenericTypeInfo
***********************************************************************/

			GenericTypeInfo::GenericTypeInfo(Ptr<ITypeInfo> _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<ITypeInfo> value)
			{
				genericArguments.Add(value);
			}

/***********************************************************************
AttributeInfoImpl
***********************************************************************/

			AttributeInfoImpl::AttributeInfoImpl(ITypeDescriptor* _attributeType)
				:attributeType(_attributeType)
			{
			}

			ITypeDescriptor* AttributeInfoImpl::GetAttributeType()
			{
				return attributeType;
			}

			vint AttributeInfoImpl::GetAttributeValueCount()
			{
				return values.Count();
			}

			ITypeDescriptor* AttributeInfoImpl::GetAttributeValueType(vint index)
			{
				return values[index].key;
			}

			Value AttributeInfoImpl::GetAttributeValue(vint index)
			{
				return values[index].value;
			}

			void AttributeInfoImpl::AddValue(ITypeDescriptor* valueType, const Value& value)
			{
#define ERROR_MESSAGE_PREFIX L"vl::reflection::description::AttributeInfoImpl::AddValue(ITypeDescriptor*, const Value&)#"
				CHECK_ERROR(valueType != nullptr, ERROR_MESSAGE_PREFIX L"valueType should not be null.");
				if (valueType->GetSerializableType())
				{
					// serializable type, no additional validation needed
				}
				else
				{
					CHECK_ERROR(
						value.GetValueType() == Value::RawPtr || value.GetValueType() == Value::Null,
						ERROR_MESSAGE_PREFIX L"ITypeDescriptor* attribute value must be a raw pointer or null."
					);
				}
#undef ERROR_MESSAGE_PREFIX
				values.Add({ valueType,value });
			}

#endif

#ifndef VCZH_DEBUG_NO_REFLECTION

/***********************************************************************
AttributeBagSource
***********************************************************************/

			void AttributeBagSource::RegisterAttribute(IMemberInfo* memberInfo, Ptr<IAttributeInfo> info)
			{
				attributes.Add(memberInfo, info);
			}

			IMemberInfo* AttributeBagSource::GetLastRegisteredMember()const
			{
				return lastRegisteredMember;
			}

			void AttributeBagSource::SetLastRegisteredMember(IMemberInfo* member)
			{
				lastRegisteredMember = member;
			}

/***********************************************************************
TypeDescriptorImplBase
***********************************************************************/

			const WString& TypeDescriptorImplBase::GetFullName()
			{
				return cppFullTypeName;
			}

			const TypeInfoContent* TypeDescriptorImplBase::GetTypeInfoContentInternal()
			{
				return typeInfoContent;
			}

			void TypeDescriptorImplBase::LoadForAttributeAccess()
			{
			}

			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()
			{
			}

			vint TypeDescriptorImplBase::GetAttributeCount()
			{
				LoadForAttributeAccess();
				return GetAttributeCountInternal(nullptr);
			}

			IAttributeInfo* TypeDescriptorImplBase::GetAttribute(vint index)
			{
				LoadForAttributeAccess();
				return GetAttributeInternal(nullptr, index);
			}

			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();
				}
			}

			void ValueTypeDescriptorBase::LoadForAttributeAccess()
			{
				Load();
			}

			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<ITypeInfo> _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<ITypeInfo> _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<parameters.Count())
				{
					return parameters[index].Obj();
				}
				else
				{
					return 0;
				}
			}

			ITypeInfo* MethodInfoImpl::GetReturn()
			{
				return returnInfo.Obj();
			}

			bool MethodInfoImpl::IsStatic()
			{
				return isStatic;
			}

			void MethodInfoImpl::CheckArguments(collections::Array<Value>& arguments)
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				if(arguments.Count()!=parameters.Count())
				{
					throw ArgumentCountMismtatchException(ownerMethodGroup);
				}
				// TODO: (enumerable) foreach
				for(vint i=0;i<parameters.Count();i++)
				{
					if(!arguments[i].CanConvertTo(parameters[i]->GetType()))
					{
						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<Value>& 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<IParameterInfo> parameter)
			{
				// TODO: (enumerable) foreach
				for(vint i=0;i<parameters.Count();i++)
				{
					if(parameters[i]->GetName()==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()
			{
			}

			vint MethodGroupInfoImpl::GetAttributeCount()
			{
				return 0;
			}

			IAttributeInfo* MethodGroupInfoImpl::GetAttribute(vint index)
			{
				return nullptr;
			}

			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<methods.Count())
				{
					return methods[index].Obj();
				}
				else
				{
					return 0;
				}
			}

			bool MethodGroupInfoImpl::AddMethod(Ptr<IMethodInfo> _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<IEventHandler> EventInfoImpl::Attach(const Value& thisObject, Ptr<IValueFunctionProxy> 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<IEventHandler> 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<IValueReadonlyList> 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<Value> 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<Value> 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<ITypeInfo> _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<IPropertyInfo> value)
			{
				properties.Add(value->GetName(), value);
				SetLastRegisteredMember(value.Obj());
				return value.Obj();
			}

			IEventInfo* TypeDescriptorImpl::AddEvent(Ptr<IEventInfo> value)
			{
				events.Add(value->GetName(), value);
				SetLastRegisteredMember(value.Obj());
				return value.Obj();
			}

			IMethodInfo* TypeDescriptorImpl::AddMethod(const WString& name, Ptr<MethodInfoImpl> value)
			{
				MethodGroupInfoImpl* methodGroup=PrepareMethodGroup(name);
				value->SetOwnerMethodgroup(methodGroup);
				methodGroup->AddMethod(value);
				SetLastRegisteredMember(value.Obj());
				return value.Obj();
			}

			IMethodInfo* TypeDescriptorImpl::AddConstructor(Ptr<MethodInfoImpl> value)
			{
				MethodGroupInfoImpl* methodGroup=PrepareConstructorGroup();
				value->SetOwnerMethodgroup(methodGroup);
				methodGroup->AddMethod(value);
				SetLastRegisteredMember(value.Obj());
				return value.Obj();
			}

			void TypeDescriptorImpl::AddBaseType(ITypeDescriptor* value)
			{
				baseTypeDescriptors.Add(value);
			}

			void TypeDescriptorImpl::Load()
			{
				if(!loaded)
				{
					loaded=true;
					LoadInternal();
				}
			}

			void TypeDescriptorImpl::LoadForAttributeAccess()
			{
				Load();
			}

			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 && index<baseTypeDescriptors.Count())
				{
					return baseTypeDescriptors[index];
				}
				else
				{
					return 0;
				}
			}

			bool TypeDescriptorImpl::CanConvertTo(ITypeDescriptor* targetType)
			{
				Load();
				if (this == targetType) return true;
				// TODO: (enumerable) foreach
				for (vint i = 0; i < baseTypeDescriptors.Count(); i++)
				{
					if (baseTypeDescriptors[i]->CanConvertTo(targetType)) return true;
				}
				return false;
			}

			vint TypeDescriptorImpl::GetPropertyCount()
			{
				Load();
				return properties.Count();
			}

			IPropertyInfo* TypeDescriptorImpl::GetProperty(vint index)
			{
				Load();
				if(0<=index && index<properties.Count())
				{
					return properties.Values().Get(index).Obj();
				}
				else
				{
					return 0;
				}
			}

			bool TypeDescriptorImpl::IsPropertyExists(const WString& name, bool inheritable)
			{
				Load();
				if(properties.Keys().Contains(name))
				{
					return true;
				}
				if(inheritable)
				{
					// TODO: (enumerable) foreach
					for(vint i=0;i<baseTypeDescriptors.Count();i++)
					{
						if(baseTypeDescriptors[i]->IsPropertyExists(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;i<baseTypeDescriptors.Count();i++)
					{
						IPropertyInfo* result=baseTypeDescriptors[i]->GetPropertyByName(name, true);
						if(result)
						{
							return result;
						}
					}
				}
				return 0;
			}

			vint TypeDescriptorImpl::GetEventCount()
			{
				Load();
				return events.Count();
			}

			IEventInfo* TypeDescriptorImpl::GetEvent(vint index)
			{
				Load();
				if(0<=index && index<events.Count())
				{
					return events.Values().Get(index).Obj();
				}
				else
				{
					return 0;
				}
			}

			bool TypeDescriptorImpl::IsEventExists(const WString& name, bool inheritable)
			{
				Load();
				if(events.Keys().Contains(name))
				{
					return true;
				}
				if(inheritable)
				{
					// TODO: (enumerable) foreach
					for(vint i=0;i<baseTypeDescriptors.Count();i++)
					{
						if(baseTypeDescriptors[i]->IsEventExists(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;i<baseTypeDescriptors.Count();i++)
					{
						IEventInfo* result=baseTypeDescriptors[i]->GetEventByName(name, true);
						if(result)
						{
							return result;
						}
					}
				}
				return 0;
			}

			vint TypeDescriptorImpl::GetMethodGroupCount()
			{
				Load();
				return methodGroups.Count();
			}

			IMethodGroupInfo* TypeDescriptorImpl::GetMethodGroup(vint index)
			{
				Load();
				if(0<=index && index<methodGroups.Count())
				{
					return methodGroups.Values().Get(index).Obj();
				}
				else
				{
					return 0;
				}
			}

			bool TypeDescriptorImpl::IsMethodGroupExists(const WString& name, bool inheritable)
			{
				Load();
				if(methodGroups.Keys().Contains(name))
				{
					return true;
				}
				if(inheritable)
				{
					// TODO: (enumerable) foreach
					for(vint i=0;i<baseTypeDescriptors.Count();i++)
					{
						if(baseTypeDescriptors[i]->IsMethodGroupExists(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;i<baseTypeDescriptors.Count();i++)
					{
						IMethodGroupInfo* result=baseTypeDescriptors[i]->GetMethodGroupByName(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> IValueEnumerable::Create(collections::LazyList<Value> values)
			{
				Ptr<IEnumerable<Value>> enumerable(new LazyList<Value>(values));
				return Ptr(new ValueEnumerableWrapper<Ptr<IEnumerable<Value>>>(enumerable));
			}

/***********************************************************************
IValueArray
***********************************************************************/

			Ptr<IValueArray> IValueArray::Create()
			{
				return Create(LazyList<Value>());
			}

			Ptr<IValueArray> IValueArray::Create(Ptr<IValueReadonlyList> values)
			{
				return Create(GetLazyList<Value>(values));
			}

			Ptr<IValueArray> IValueArray::Create(collections::LazyList<Value> values)
			{
				auto list = Ptr(new Array<Value>);
				CopyFrom(*list.Obj(), values);
				return Ptr(new ValueArrayWrapper<Ptr<Array<Value>>>(list));
			}

/***********************************************************************
IValueList
***********************************************************************/

			Ptr<IValueList> IValueList::Create()
			{
				return Create(LazyList<Value>());
			}

			Ptr<IValueList> IValueList::Create(Ptr<IValueReadonlyList> values)
			{
				return Create(GetLazyList<Value>(values));
			}

			Ptr<IValueList> IValueList::Create(collections::LazyList<Value> values)
			{
				auto list = Ptr(new List<Value>);
				CopyFrom(*list.Obj(), values);
				return Ptr(new ValueListWrapper<Ptr<List<Value>>>(list));
			}

/***********************************************************************
IObservableList
***********************************************************************/

			class ReversedObservableList : public ObservableListBase<Value>
			{
			protected:

				void NotifyUpdateInternal(vint start, vint count, vint newCount)override
				{
					if (observableList)
					{
						observableList->ItemChanged(start, count, newCount);
					}
				}
			public:
				IValueObservableList*		observableList = nullptr;
			};

			Ptr<IValueObservableList> IValueObservableList::Create()
			{
				return Create(LazyList<Value>());
			}

			Ptr<IValueObservableList> IValueObservableList::Create(Ptr<IValueReadonlyList> values)
			{
				return Create(GetLazyList<Value>(values));
			}

			Ptr<IValueObservableList> IValueObservableList::Create(collections::LazyList<Value> values)
			{
				auto list = Ptr(new ReversedObservableList);
				CopyFrom(*list.Obj(), values);
				auto wrapper = Ptr(new ValueObservableListWrapper<Ptr<ReversedObservableList>>(list));
				list->observableList = wrapper.Obj();
				return wrapper;
			}

/***********************************************************************
IValueDictionary
***********************************************************************/

			Ptr<IValueDictionary> IValueDictionary::Create()
			{
				auto dictionary = Ptr(new Dictionary<Value, Value>);
				return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(dictionary));
			}

			Ptr<IValueDictionary> IValueDictionary::Create(Ptr<IValueReadonlyDictionary> values)
			{
				auto dictionary = Ptr(new Dictionary<Value, Value>);
				CopyFrom(*dictionary.Obj(), GetLazyList<Value, Value>(values));
				return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(dictionary));
			}

			Ptr<IValueDictionary> IValueDictionary::Create(collections::LazyList<collections::Pair<Value, Value>> values)
			{
				auto dictionary = Ptr(new Dictionary<Value, Value>);
				CopyFrom(*dictionary.Obj(), values);
				return Ptr(new ValueDictionaryWrapper<Ptr<Dictionary<Value, Value>>>(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<IValueReadonlyList> GetCallStack()override
				{
					return nullptr;
				}
			};

			Ptr<IValueException> 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<bool>::GetDefaultValue()
			{
				return false;
			}

			bool TypedValueSerializerProvider<bool>::Serialize(const bool& input, WString& output)
			{
				output = input ? L"true" : L"false";
				return true;
			}

			bool TypedValueSerializerProvider<bool>::Deserialize(const WString& input, bool& output)
			{
				output = input == L"true";
				return input == L"true" || input == L"false";
			}

/***********************************************************************
wchar_t
***********************************************************************/

			wchar_t TypedValueSerializerProvider<wchar_t>::GetDefaultValue()
			{
				return 0;
			}

			bool TypedValueSerializerProvider<wchar_t>::Serialize(const wchar_t& input, WString& output)
			{
				output = input ? WString::FromChar(input) : L"";
				return true;
			}

			bool TypedValueSerializerProvider<wchar_t>::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<WString>::GetDefaultValue()
			{
				return L"";
			}

			bool TypedValueSerializerProvider<WString>::Serialize(const WString& input, WString& output)
			{
				output = input;
				return true;
			}

			bool TypedValueSerializerProvider<WString>::Deserialize(const WString& input, WString& output)
			{
				output = input;
				return true;
			}

/***********************************************************************
Locale
***********************************************************************/

			Locale TypedValueSerializerProvider<Locale>::GetDefaultValue()
			{
				return Locale();
			}

			bool TypedValueSerializerProvider<Locale>::Serialize(const Locale& input, WString& output)
			{
				output = input.GetName();
				return true;
			}

			bool TypedValueSerializerProvider<Locale>::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"(<Y>/d/d/d/d)-(<M>/d/d)-(<D>/d/d) (<h>/d/d):(<m>/d/d):(<s>/d/d).(<ms>/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<DateTime>::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<DateTime>::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<DateTime>::Deserialize(const WString& input, DateTime& output)
			{
				auto& dts = GetDateTimeSerializerStorage();
				Ptr<RegexMatch> 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
***********************************************************************/


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::IAttributeInfo, system::reflection::AttributeInfo)
			IMPL_TYPE_INFO_RENAME(vl::reflection::description::IAttributeBag, system::reflection::AttributeBag)
			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<DescriptableObject>
			{
			public:
				class CustomTypeDescriptorImpl : public TypeDescriptorImpl
				{
				public:
					CustomTypeDescriptorImpl()
						:TypeDescriptorImpl(TypeDescriptorFlags::Class, &TypeInfo<DescriptableObject>::content)
					{
						Description<DescriptableObject>::SetAssociatedTypeDescriptor(this);
					}
					~CustomTypeDescriptorImpl()
					{
						Description<DescriptableObject>::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<DateTime>());
				serializableType = Ptr(new SerializableType<DateTime>());
				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(osMilliseconds)
				STRUCT_MEMBER(osInternal)
			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<IValueArray>(), NO_PARAMETER, vl::reflection::description::IValueArray::Create)
				CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueArray>(Ptr<IValueReadonlyList>), { 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<IValueList>(), NO_PARAMETER, vl::reflection::description::IValueList::Create)
				CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueList>(Ptr<IValueReadonlyList>), { 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<IValueObservableList>(), NO_PARAMETER, vl::reflection::description::IValueObservableList::Create)
				CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueObservableList>(Ptr<IValueReadonlyList>), { 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<IValueDictionary>(), NO_PARAMETER, vl::reflection::description::IValueDictionary::Create)
				CLASS_MEMBER_EXTERNALCTOR(Ptr<IValueDictionary>(Ptr<IValueReadonlyDictionary>), { 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(IAttributeInfo)
				CLASS_MEMBER_PROPERTY_READONLY_FAST(AttributeType)
				CLASS_MEMBER_PROPERTY_READONLY_FAST(AttributeValueCount)
				CLASS_MEMBER_METHOD(GetAttributeValueType, { L"index" })
				CLASS_MEMBER_METHOD(GetAttributeValue, { L"index" })
			END_INTERFACE_MEMBER(IAttributeInfo)

			BEGIN_INTERFACE_MEMBER_NOPROXY(IAttributeBag)
				CLASS_MEMBER_PROPERTY_READONLY_FAST(AttributeCount)
				CLASS_MEMBER_METHOD(GetAttribute, { L"index" })
			END_INTERFACE_MEMBER(IAttributeBag)

			BEGIN_INTERFACE_MEMBER_NOPROXY(IMemberInfo)
				CLASS_MEMBER_BASE(IAttributeBag)
				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_BASE(IAttributeBag)

				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<Value>::content.typeName, Ptr(new TypedValueTypeDescriptorBase<Value, TypeDescriptorFlags::Object>));
#define ADD_PRIMITIVE_TYPE(TYPE) manager->SetTypeDescriptor(TypeInfo<TYPE>::content.typeName, Ptr(new PrimitiveTypeDescriptor<TYPE>()));
					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;
			}
		}
	}
}

