/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "VlppOS.h"
#include "Vlpp.h"
#include "VlppRegex.h"

/***********************************************************************
.\DESCRIPTABLEOBJECT.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_DESCRIPTABLEOBJECT
#define VCZH_REFLECTION_DESCRIPTABLEOBJECT


#if (defined VCZH_DEBUG_NO_REFLECTION) && (defined VCZH_DEBUG_METAONLY_REFLECTION)
static_assert(false, "Preprocessor VCZH_DEBUG_NO_REFLECTION and VCZH_DEBUG_METAONLY_REFLECTION could not be defined at the same time.")
#endif

#if !(defined VCZH_DEBUG_NO_REFLECTION) && !(defined VCZH_DEBUG_METAONLY_REFLECTION)
#define VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
#endif

namespace vl
{
	namespace reflection
	{
		namespace description
		{
			class ITypeDescriptor;
		}

/***********************************************************************
DescriptableObject
***********************************************************************/

		/// <summary>
		/// <p>
		/// Base class of all reflectable value types (class).
		/// If you want to create a reflectable class, you should inherit from [T:vl.reflection.Description`1].
		/// </p>
		/// <p>
		/// Inheriting from [T:vl.reflection.Description`1] is necessary even if you turned on "VCZH_DEBUG_NO_REFLECTION" preprocessor definition.
		/// In this case, some members will be removed from this class to reduce the object size.
		/// </p>
		/// <p>
		/// <b>Ptr&lt;DescriptableObject&gt;</b> is recommended to replace <b>Ptr&lt;Object&gt;</b> for holding a reflectable object.
		/// When a class <b>T</b> inherits from [T:vl.reflection.Description`1], including <b>DescriptableObject</b> itself,
		/// <b>Ptr&lt;T&gt;</b> is safe to be created directly from a <b>T*</b> hold by another <b>Ptr&lt;T&gt;</b>.
		/// This is not allowed for all classes that do not inherit from [T:vl.reflection.Description`1].
		/// </p>
		/// </summary>
		/// <remarks>
		/// <p>
		/// When a class in Workflow script inherits from a class in C++,
		/// since it is not possible to actually create a class in runtime,
		/// so the created object from this Workflow class is multiple <b>DescriptableObject</b> grouping together.
		/// </p>
		/// <p>
		/// This is called <b>aggregation</b>.
		/// </p>
		/// <p>
		/// In this case, <see cref="SafeAggregationCast`1"/> is required to do pointer casting to a C++ class.
		/// </p>
		/// <p>
		/// To allow a C++ class to be aggregated,
		/// use [T:vl.reflection.AggregatableDescription`1] instead of [T:vl.reflection.Description`1],
		/// and call <see cref="FinalizeAggregation"/> in the destructor.
		/// If A inherits B and they are all aggregatable, do it in both destructors.
		/// </p>
		/// </remarks>
		/// <example><![CDATA[
		/// class MyClass : public Object, public Description<MyClass>
		/// {
		/// public:
		///     WString data;
		/// };
		/// 
		/// int main()
		/// {
		///     auto myClass = Ptr(new MyClass);
		///     myClass->data = L"Hello, world!";
		/// 
		///     Ptr<DescriptableObject> obj = myClass;
		///     Console::WriteLine(obj.Cast<MyClass>()->data);
		/// 
		///     // usually you cannot do this directly
		///     // because obj and myClass share the same reference counter, but myClass2 doesn't
		///     // this will cause the destructor delete MyClass twice and crash
		///     // but it is different when MyClass inherits from Description<MyClass> or AggregatableDescription<MyClass>
		///     auto myClass2 = Ptr<MyClass>(dynamic_cast<MyClass*>(obj.Obj()));
		///     Console::WriteLine(myClass2->data);
		/// }
		/// ]]></example>
		class DescriptableObject
		{
			template<typename T, typename Enabled>
			friend struct vl::ReferenceCounterOperator;
			template<typename T>
			friend class Description;

			typedef collections::Dictionary<WString, Ptr<Object>>		InternalPropertyMap;
			typedef bool(*DestructorProc)(DescriptableObject* obj, bool forceDisposing);
		private:
			atomic_vint								referenceCounter;

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			size_t									objectSize;
			description::ITypeDescriptor**			typeDescriptor;
#endif
			Ptr<InternalPropertyMap>				internalProperties;


#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			bool									destructing;
			DescriptableObject**					aggregationInfo;
			vint									aggregationSize;
#endif

		protected:
			DestructorProc							sharedPtrDestructorProc;

		protected:

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			// Returns true if this object inherits other objects by aggregation.</returns>
			bool									IsAggregated();

			// Returnd the number of aggregated base objects.</returns>
			vint									GetAggregationSize();

			// Return the object that inherit this object.</returns>
			DescriptableObject*						GetAggregationRoot();

			// Notice that an object inherit this object, it is called by SetAggregationParent
			void									SetAggregationRoot(DescriptableObject* value);

			// Return the specified aggregated base object
			DescriptableObject*						GetAggregationParent(vint index);

			// Set an aggregated base class
			void									SetAggregationParent(vint index, DescriptableObject* value);

			// Set an aggregated base class
			void									SetAggregationParent(vint index, Ptr<DescriptableObject>& value);

			// Must be called in Workflow generated classes that inherit from aggregatable C++ classes.
			void									InitializeAggregation(vint size);
#endif
			/// <summary>A function that must be called in destructors of all classes inheriting from [T:vl.reflection.AggregatableDescription`1].</summary>
			void									FinalizeAggregation();

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			template<typename T>
			void SafeAggregationCast(T*& result)
			{
				auto expected = dynamic_cast<T*>(this);
				if (expected)
				{
					CHECK_ERROR(result == nullptr, L"vl::reflection::DescriptableObject::SafeAggregationCast<T>()#Found multiple ways to do aggregation cast.");
					result = expected;
				}
				if (IsAggregated())
				{
					for (vint i = 0; i < aggregationSize; i++)
					{
						if (auto parent = GetAggregationParent(i))
						{
							parent->SafeAggregationCast<T>(result);
						}
					}
				}
			}
#endif
		public:
			DescriptableObject();
			virtual ~DescriptableObject();

			// all fields are describing the object, it would be incorrect if they are copied from one to another.
			DescriptableObject(const DescriptableObject&) : DescriptableObject() {}
			DescriptableObject(DescriptableObject&&) : DescriptableObject() {}
			DescriptableObject& operator=(const DescriptableObject&) { return *this; }
			DescriptableObject& operator=(DescriptableObject&&) { return *this; }

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			/// <summary>
			/// <p>Get the type descriptor that describe the real type of this object.</p>
			/// </summary>
			/// <returns>The real type.</returns>
			/// <remarks>
			/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
			/// </remarks>
			description::ITypeDescriptor*			GetTypeDescriptor();
#endif

			/// <summary>
			/// Get an internal property of this object.
			/// Internal properties are totally for customization,
			/// they do not affect the object in anyway.
			/// </summary>
			/// <returns>Value of the internal property of this object.</returns>
			/// <param name="name">Name of the property.</param>
			Ptr<Object>								GetInternalProperty(const WString& name);
			/// <summary>
			/// Set an internal property of this object.
			/// Internal properties are totally for customization,
			/// they do not affect the object in anyway.
			/// </summary>
			/// <param name="name">Name of the property.</param>
			/// <param name="value">Value of the internal property of this object.</param>
			void									SetInternalProperty(const WString& name, Ptr<Object> value);
			/// <summary>Try to delete this object.</summary>
			/// <returns>Returns true if this operation succeeded. Returns false if the object refuces to be dispose.</returns>
			/// <param name="forceDisposing">Set to true to force disposing this object. If the reference counter is not 0 if you force disposing it, it will raise a [T:vl.reflection.description.ValueNotDisposableException].</param>
			bool									Dispose(bool forceDisposing);

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			/// <summary>
			/// <p>Get the aggregation root object, which is the object that inherits this object by aggregation.</p>
			/// </summary>
			/// <returns>The aggregation root object. If this object is not aggregated, or it is the root object of others, than this function return itself.</returns>
			/// <remarks>
			/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
			/// </remarks>
			DescriptableObject*						SafeGetAggregationRoot();

#endif
			/// <summary>Cast the object to another type, this is required when the object is involved in aggregation.</summary>
			/// <returns>The object with the expected type in all involved aggregated objects. It will crash when multiple objects are found to be qualified.</returns>
			/// <typeparam name="T">The expected type to cast.</typeparam>
			/// <remarks>
			/// <p>
			/// A workflow class could inherit from multiple aggregatable C++ classes.
			/// </p>
			/// <p>
			/// In order to do pointer casting correctly,
			/// this function allow you to cast from one aggregated C++ base object to another aggregated C++ base object,
			/// even when these two objects are not involved in inheriting in C++.
			/// </p>
			/// <p>
			/// When <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>on</b>, it performs dynamic_cast.
			/// </p>
			/// </remarks>
			template<typename T>
			T* SafeAggregationCast()
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				T* result = nullptr;
				SafeGetAggregationRoot()->SafeAggregationCast<T>(result);
				return result;
#else
				return dynamic_cast<T*>(this);
#endif
			}
		};
		
		/// <summary>
		/// <p>
		/// Inherit from this class when you want to create a reflectable class.
		/// It should be used like this:
		/// <program><code><![CDATA[
		/// class YourClass : public Description<YourClass>
		/// {
		///     ..
		/// };
		/// ]]></code></program>
		/// </p>
		/// <p>
		/// If you want YourClass to be inheritable in scripts,
		/// instead of using Description,
		/// you should use <see cref="AggregatableDescription`1"/>, like this:
		/// <program><code><![CDATA[
		/// class YourClass : public AggregatableDescription<YourClass>
		/// {
		///     ~YourClass()
		///     {
		///         FinalizeAggregation();
		///     }
		/// };
		/// ]]></code></program>
		/// </p>
		/// <p>
		/// After you complete your type,
		/// use the following macros and functions to register your class into the global type table.
		/// </p>
		/// <p>
		/// Some of the predefined type has already been registered.
		/// If your types depend on these types, you should load those types by calling some or all of them:
		/// <ul>
		///     <li>[F:vl.reflection.description.LoadPredefinedTypes]</li>
		///     <li>[F:vl.reflection.description.LoadParsingTypes]</li>
		///     <li>[F:vl.reflection.description.JsonLoadTypes]</li>
		///     <li>[F:vl.reflection.description.XmlLoadTypes]</li>
		/// </ul>
		/// But if you link <b>GacUIReflection.cpp</b> in your project and set <b>VCZH_DEBUG_NO_REFLECTION</b> to off,
		/// all types will be automatically loaded before <b>GuiMain</b> is called.
		/// </p>
		/// <p>
		/// The order does not matter, because content of types are lazily loaded.
		/// </p>
		/// <p>
		/// Everything below should be put in <b>vl::reflection::description</b> namespaces.
		/// <ol>
		///     <li>
		///         <b>(in header files)</b> Create a macro that contains all types that you want to register.
		///         Content in the list will become full names for registered type,
		///         so it is strongly recommended to use the full name.
		///         <program><code><![CDATA[
		///             #define MY_TYPELIST(F)\
		///                 F(mynamespaces::MyClass1)\
		///                 F(mynamespaces::MyClass2)\
		///         ]]></code></program>
		///     </li>
		///     <li>
		///         <b>in header files)</b> Connect type names and types:
		///         <program><code><![CDATA[
		///             MY_TYPELIST(DECL_TYPE_INFO)
		///         ]]></code></program>
		///     </li>
		///     <li>
		///         <b>(in cpp files)</b> Connect type names and types:
		///         <program><code><![CDATA[
		///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
		///         ]]></code></program>
		///     </li>
		///     <li>
		///         <b>(in cpp files)</b> Register all members:
		///         <ul>
		///             <li>
		///                 You will need to define a macro for commas, Whatever name is fine.
		///                 <program><code><![CDATA[
		///                     #define _ ,
		///                 ]]></code></program>
		///             </li>
		///             <li>
		///                 <b>enum</b>:
		///                 use <b>BEGIN_ENUM_ITEM_MERGABLE</b> instead of <b>BEGIN_ENUM_ITEM</b> if enum items are flags instead of concrete items.
		///                 <program><code><![CDATA[
		///                     BEGIN_ENUM_ITEM(Season)
		///                         ENUM_ITEM(Spring)
		///                         ENUM_ITEM(Summer)
		///                         ENUM_ITEM(Autumn)
		///                         ENUM_ITEM(Winter)
		///                     END_ENUM_ITEM(Season)
		///                 ]]></code></program>
		///             </li>
		///             <li>
		///                 <b>enum class:</b>
		///                 use <b>BEGIN_ENUM_ITEM_MERGABLE</b> instead of <b>BEGIN_ENUM_ITEM</b> if enum items are flags instead of concrete items.
		///                 <program><code><![CDATA[
		///                     BEGIN_ENUM_ITEM(Season)
		///                         ENUM_CLASS_ITEM(Spring)
		///                         ENUM_CLASS_ITEM(Summer)
		///                         ENUM_CLASS_ITEM(Autumn)
		///                         ENUM_CLASS_ITEM(Winter)
		///                     END_ENUM_ITEM(Season)
		///                 ]]></code></program>
		///             </li>
		///             <li>
		///                 <b>struct</b>:
		///                 It doesn't necessary mean a struct in C++.
		///                 Structs in reflection and Workflow script mean value types that carry only data, without methods and inheritance.
		///                 <program><code><![CDATA[
		///                     BEGIN_STRUCT_MEMBER(Point)
		///                         STRUCT_MEMBER(x)
		///                         STRUCT_MEMBER(y)
		///                     END_STRUCT_MEMBER(Point)
		///                 ]]></code></program>
		///             </li>
		///             <li>
		///                 <p>
		///                 <b>class</b>:
		///                 It doesn't necessary mean a class in C++.
		///                 Classes in reflection and Workflow script mean reference types.
		///                 </p>
		///                 <p>
		///                 Here are all macros that register content of classes
		///                 <ul>
		///                     <li>CLASS_MEMBER_BASE</li>
		///                     <li>CLASS_MEMBER_FIELD</li>
		///                     <li>CLASS_MEMBER_CONSTRUCTOR</li>
		///                     <li>CLASS_MEMBER_EXTERNALCTOR(_TEMPLATE)?</li>
		///                     <li>CLASS_MEMBER_METHOD(_OVERLOAD)?_RENAME</li>
		///                     <li>CLASS_MEMBER_(STATIC_)?METHOD(_OVERLOAD)?</li>
		///                     <li>CLASS_MEMBER_(STATIC_)?EXTERNALMETHOD(_TEMPLATE)?</li>
		///                     <li>CLASS_MEMBER_PROPERTY(_EVENT)?(_READONLY)?(_FAST)?</li>
		///                     <li>CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE</li>
		///                     <li>CLASS_MEMBER_EVENT</li>
		///                 </ul>
		///                 </p>
		///                 <p>
		///                 <program><code><![CDATA[
		///                     BEGIN_CLASS_MEMBER(MyClass)
		///
		///                         // 01) Declare a base class (can have multiple base classes).
		///                         CLASS_MEMBER_BASE(MyBaseClass)
		///
		///                         // 02) Declare a field.
		///                         CLASS_MEMBER_FIELD(myField)
		///
		///                         // 03) Default constructor that results in a raw pointer.
		///                         CLASS_MEMBER_CONSTRUCTIOR(MyClass*(), NO_PARAMETER)
		///
		///                         // 04) Default constructor that results in a shared pointer.
		///                         CLASS_MEMBER_CONSTRUCTIOR(Ptr<MyClass>(), NO_PARAMETER)
		///
		///                         // 05) Constructor with arguments.
		///                         CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"})
		///
		///                         // 06) Inject a global function as a constructor.
		///                         CLASS_MEMBER_EXTERNALCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, mynamespace::CreateMyClass)
		///
		///                         // 07) Inject a consturctor and specify how to generate C++ code, "*" means not able to generate.
		///                         CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, CreateMyClass, L"mynamespace::GetMyClass($Arguments)", L"::vl::Func<$Func>(&mynamespace::GetMyClass)")
		///                         CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(), NO_PARAMETER, []()->Ptr<MyClass>{return nullptr;}, L"*", L"*")
		///
		///                         // 08) Add unoverloaded functions.
		///                         CLASS_MEMBER_METHOD(MyFunction1, NO_PARAMETER)
		///                         CLASS_MEMBER_METHOD(MyFunction2, {L"parameter1" _ L"parameter2"})
		///
		///                         // 09) Add unoverloaded functions but give different names. Unoverloaded only means in C++, not in renamed functions.
		///                         CLASS_MEMBER_METHOD_RENAME(MyNewName1, MyFunction1, NO_PARAMETER)
		///                         CLASS_MEMBER_METHOD_RENAME(MyNewName2, MyFunction2, {L"parameter1" _ L"parameter2"})
		///
		///                         // 10) Add overloaded functions, with function type specified in method pointers
		///                         CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, NO_PARAMETER, int(MyClass::*)())
		///                         CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter"}, int(MyClass::*)(int))
		///                         CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
		///
		///                         // 11) Add overloaded functions but give different names.
		///                         CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName3, MyFunction3, NO_PARAMETER, int(MyClass::*)())
		///                         CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter"}, int(MyClass::*)(int))
		///                         CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
		///
		///                         // 12) Inject global functions as methods:
		///                         CLASS_MEMBER_EXTERNALMETHOD(MyNewName5, {L"parameter"}, int(MyClass::*)(int), mynamespace::AGlobalFunction)
		///
		///                         // 13) Inject a method and specify how to generate C++ code, "*" means not able to generate.
		///                         CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(MyNewName5, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&), [](MyClass* a, int b, const WString& c){return 0;}, L"*", L"*")
		///
		///                         // 14) Add unoverloaded static functions
		///                         CLASS_MEMBER_STATIC_METHOD(MyFunction4, NO_PARAMETER)
		///                         CLASS_MEMBER_STATIC_METHOD(MyFunction5, {L"parameter1" _ L"parameter2"})
		///
		///                         // 15) Add overloaded static functions
		///                         CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, NO_PARAMETER, int(*)())
		///                         CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, {L"parameter"}, int(*)(int))
		///                         CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&))
		///
		///                         // 16) Inject global functions as static methods:
		///                         CLASS_MEMBER_STATIC_EXTERNALMETHOD(MyNewName6, {L"parameter"}, int(*)(int), mynamespace::AGlobalFunction2)
		///
		///                         // 17) Inject a static method and specify how to generate C++ code, "*" means not able to generate.
		///                         CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(MyNewName6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&), [](int b, const WString& c){return 0;}, L"*")
		///
		///                         // 18) Add a getter function as a property
		///                         CLASS_MEMBER_PROPERTY_READONLY_FAST(X)
		///                         // which is short for
		///                         CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
		///                         CLASS_MEMBER_PROPERTY_READONLY(X, GetX)
		///
		///                         // 19) Add a pair of getter and setter functions as a property
		///                         CLASS_MEMBER_PROPERTY_FAST(X)
		///                         // which is short for
		///                         CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
		///                         CLASS_MEMBER_METHOD(SetX, {L"value"})
		///                         CLASS_MEMBER_PROPERTY(X, GetX, SetX)
		///
		///                         // 20) Add a getter function as a property with a property changed event
		///                         CLASS_MEMBER_EVENT(XChanged)
		///                         CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(X, XChanged)
		///                         // which is short for
		///                         CLASS_MEMBER_EVENT(XChanged)
		///                         CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
		///                         CLASS_MEMBER_PROPERTY_EVENT_READONLY(X, GetX, XChanged)
		///
		///                         // 21) Add a pair of getter and setter functions as a property with a property changed event
		///                         CLASS_MEMBER_EVENT(XChanged)
		///                         CLASS_MEMBER_PROPERTY_EVENT_FAST(X, XChanged)
		///                         // which is short for
		///                         CLASS_MEMBER_EVENT(XChanged)
		///                         CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
		///                         CLASS_MEMBER_METHOD(SetX, {L"value"})
		///                         CLASS_MEMBER_PROPERTY_EVENT(X, GetX, SetX, XChanged)
		///
		///                         // 22) Attach an attribute to the type itself. The attribute type must be a reflected struct.
		///                         //     Each argument must be a serializable primitive value. Zero arguments are allowed.
		///                         ATTRIBUTE_TYPE(MyAttribute, L"name", 100)
		///                         ATTRIBUTE_TYPE(EmptyAttribute)
		///
		///                         // 23) Attach an attribute to the most recently registered member (field, property, event, method, or constructor).
		///                         //     Must appear after the member registration macro it decorates.
		///                         CLASS_MEMBER_FIELD(fieldValue)
		///                         ATTRIBUTE_MEMBER(MyAttribute, L"field", 1)
		///                         ATTRIBUTE_MEMBER(EmptyAttribute)
		///
		///                         // 24) Attach an attribute to a named parameter of the most recently registered method or constructor.
		///                         //     The parameter name must match exactly one parameter.
		///                         CLASS_MEMBER_METHOD(MyFunction2, {L"parameter1" _ L"parameter2"})
		///                         ATTRIBUTE_PARAMETER(L"parameter1", MyAttribute, L"param", 2)
		///
		///                     END_CLASS_MEMBER(MyClass)
		///                 ]]></code></program>
		///                 </p>
		///                 <p>
		///                 If the code compiles, the class should look like this:
		///                 <program><code><![CDATA[
		///                     class MyClass : public Description<MyClass>
		///                     {
		///                     public:
		///                         MyClass();
		///                         MyClass(int numberParameter, const WString& stringParameter);
		///
		///                         int MyFunction1();
		///                         int MyFunction2(int parameter1, const WString& parameter2);
		///                         int MyFunction3();
		///                         int MyFunction3(int parameter);
		///                         int MyFunction3(int parameter1, const WString& parameter2);
		///
		///                         static int MyFunction4();
		///                         static int MyFunction5(int parameter1, const WString& parameter2);
		///                         static int MyFunction6();
		///                         static int MyFunction6(int parameter);
		///                         static int MyFunction6(int parameter1, const WString& parameter2);
		///
		///                         Event<void()> XChanged;
		///                         int GetX();
		///                         void SetX(int value);
		///                     };
		///
		///                     Ptr<MyClass> CreateMyClass(int numberParameter, const WString7 stringParameter);
		///                     int GlobalFunction(MyClass* self, int parameter);
		///                 ]]></code></program>
		///                 </p>
		///             </li>
		///             <li>
		///                 <p>
		///                 <b>interface</b>:
		///                 A C++ class can be registered as a reflectable interface if:
		///                 <ul>
		///                     <li>Directly or indirectly inherits [T:vl.reflection.IDescriptable]</li>
		///                     <li>The only registered constructor (if exists) should use Ptr&lt;[T:vl.reflection.description.IValueInterfaceProxy]&gt; as a parameter, so that a Workflow script class could implement this interface.</li>
		///                 </ul>
		///                 </p>
		///                 <p>
		///                 Suppose you have an interface like this:
		///                 <program><code><![CDATA[
		///                     class IMyInterface : public virtual IDescriptable, public Description<IMyInterface>
		///                     {
		///                     public:
		///                         int GetX();
		///                         void SetX(int value);
		///                     };
		///                 ]]></code></program>
		///                 </p>
		///                 <p>
		///                 If you want to allow a Workflow script class implement this interface, you should first add a proxy like this:
		///                 <program><code><![CDATA[
		///                     #pragma warning(push)
		///                     #pragma warning(disable:4250)
		///                     BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(IMyInterface)
		///                         // or BEGIN_INTERFACE_PROXY_RAWPTR(IMyInterface, baseInterfaces...)
		///                         // or BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IMyInterface)
		///                         // or BEGIN_INTERFACE_PROXY_SHAREDPTR(IMyInterface, baseInterfaces...)
		///                         int GetX()override
		///                         {
		///                             INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetX)
		///                         }
		///
		///                         void SetX(int value)override
		///                         {
		///                             INVOKE_INTERFACE_PROXY(SetX, value)
		///                         }
		///                     END_INTERFACE_PROXY(IMyInterface)
		///                     #pragma warning(pop)
		///                 ]]></code></program>
		///                 </p>
		///                 <p>
		///                 And then use this code to register the interface:
		///                 <program><code><![CDATA[
		///                     BEGIN_INTERFACE_MEMBER(IMyInterface)
		///                         ...
		///                     END_INTERFACE_MEMBER(IMyInterface)
		///                 ]]></code></program>
		///                 </p>
		///                 <p>
		///                 Everything else is the same as registering classes.
		///                 Use <b>BEGIN_INTERFACE_MEMBER_NOPROXY</b> to register an interface without a proxy,
		///                 which means a Workflow script class cannot implement this interface.
		///                 </p>
		///             </li>
		///             <li>
		///                 Undefine the macro for comma:
		///                 <program><code><![CDATA[
		///                     #undef _
		///                 ]]></code></program>
		///             </li>
		///         </ul>
		///     </li>
		///     <li>
		///         <b>(in cpp files)</b> Create a type loader:
		///         <program><code><![CDATA[
		///             class MyTypeLoader : public Object, public ITypeLoader
		///             {
		///             public:
		///                 void Load(ITypeManager* manager)
		///                 {
		///                     MY_TYPELIST(ADD_TYPE_INFO)
		///                 }
		///
		///                 void Unload(ITypeManager* manager)
		///                 {
		///                 }
		///             };
		///         ]]></code></program>
		///     </li>
		///     <li>
		///         Before using reflection on registered types, you need to register the type loader:
		///         <program><code><![CDATA[
		///             vl::reflection::description::GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
		///         ]]></code></program>
		///     </li>
		/// </ol>
		/// </p>
		/// </summary>
		/// <typeparam name="T">Type that inherit this class.</typeparam>
		template<typename T>
		class Description : public virtual DescriptableObject
		{
		protected:
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			static description::ITypeDescriptor*		associatedTypeDescriptor;
#endif
		public:
			Description()
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

				if(objectSize<sizeof(T))
				{
					objectSize=sizeof(T);
					if(!typeDescriptor || !*typeDescriptor || associatedTypeDescriptor)
					{
						typeDescriptor=&associatedTypeDescriptor;
					}
				}
#endif
			}

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			static description::ITypeDescriptor* GetAssociatedTypeDescriptor()
			{
				return associatedTypeDescriptor;
			}

			static void SetAssociatedTypeDescriptor(description::ITypeDescriptor* typeDescroptor)
			{
				associatedTypeDescriptor=typeDescroptor;
			}
#endif
		};

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
		template<typename T>
		description::ITypeDescriptor* Description<T>::associatedTypeDescriptor = 0;
#endif

/***********************************************************************
AggregatableDescription
***********************************************************************/

		/// <summary>
		/// Inherit from this class when you want to create a reflectable class that can be inherited by Workflow script classes.
		/// </summary>
		/// <typeparam name="T">Type that inherit this class.</typeparam>
		template<typename T>
		class AggregatableDescription : public Description<T>
		{
		};

/***********************************************************************
IDescriptable
***********************************************************************/

		/// <summary>Base type of all reflectable interfaces. All reflectable interface types should be virtual inherited.</summary>
		class IDescriptable : public virtual Interface, public Description<IDescriptable>
		{
		public:
			~IDescriptable(){}
		};

/***********************************************************************
ReferenceCounterOperator
***********************************************************************/
	}

	template<typename T>
	struct ReferenceCounterOperator<T, std::enable_if_t<std::is_convertible_v<T*, reflection::DescriptableObject*>>>
	{
		static __forceinline atomic_vint* CreateCounter(T* reference)
		{
			reflection::DescriptableObject* obj=reference;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			if (obj->IsAggregated())
			{
				if (auto root = obj->GetAggregationRoot())
				{
					return &root->referenceCounter;
				}
			}
#endif
			return &obj->referenceCounter;
		}

		static __forceinline void DeleteReference(atomic_vint* counter, void* reference)
		{
			reflection::DescriptableObject* obj=(T*)reference;
			obj->Dispose(false);
		}
	};

	namespace reflection
	{
		namespace description
		{
/***********************************************************************
Exceptions
***********************************************************************/

			class TypeDescriptorException abstract : public Exception
			{
			public:
				TypeDescriptorException(const WString& message)
					:Exception(message)
				{
				}
			};

			class ObjectDisposedException : public TypeDescriptorException
			{
			public:
				ObjectDisposedException()
					:TypeDescriptorException(L"The referenced native object has been disposed.")
				{
				}
			};

			class ValueNotDisposableException : public TypeDescriptorException
			{
			public:
				ValueNotDisposableException()
					:TypeDescriptorException(L"Cannot dispose an object whose reference counter is not 0.")
				{
				}
			};
		}
	}
}

#endif

/***********************************************************************
.\DESCRIPTABLEVALUE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_DESCRIPTABLEVALUE
#define VCZH_REFLECTION_DESCRIPTABLEVALUE


namespace vl
{
	namespace reflection
	{
		namespace description
		{
			class ITypeInfo;
			class IMethodGroupInfo;
			class IMethodInfo;
			class IPropertyInfo;
			class IEventInfo;
			class IEventHandler;
			class IValueFunctionProxy;
		}

		namespace description
		{
/***********************************************************************
Value
***********************************************************************/

			enum class PredefinedBoxableType : vint
			{
				PBT_Unknown = -1,
				PBT_S8, PBT_S16, PBT_S32, PBT_S64,
				PBT_U8, PBT_U16, PBT_U32, PBT_U64,
				PBT_F32, PBT_F64,
				PBT_BOOL,
				PBT_WCHAR,
				PBT_STRING,
				PBT_LOCALE,
				PBT_DATETIME,
			};

			class IBoxedValue : public virtual IDescriptable, public Description<IBoxedValue>
			{
			public:
				enum CompareResult
				{
					Smaller,
					Greater,
					Equal,
					NotComparable,
				};

				virtual PredefinedBoxableType	GetBoxableType() = 0;
				virtual Ptr<IBoxedValue>		Copy() = 0;
				virtual CompareResult			ComparePrimitive(Ptr<IBoxedValue> boxedValue) = 0;
			};

			/// <summary>A type to store all values of reflectable types.</summary>
			/// <remarks>
			/// To convert between <b>Value</b> and its real C++ type, the following functions are recommended:
			/// <ul>
			///     <li>[F:vl.reflection.description.BoxValue`1]</li>
			///     <li>[F:vl.reflection.description.UnboxValue`1]</li>
			///     <li>[F:vl.reflection.description.BoxParameter`1]</li>
			///     <li>[F:vl.reflection.description.UnboxParameter`1]</li>
			/// </ul>
			/// </remarks>
			class Value : public Object
			{
			public:
				/// <summary>How the value is stored.</summary>
				enum ValueType
				{
					/// <summary>The value is null.</summary>
					Null,
					/// <summary>The reference value is stored using a raw pointer.</summary>
					RawPtr,
					/// <summary>The reference value is stored using a shared pointer.</summary>
					SharedPtr,
					/// <summary>The value is stored by boxing.</summary>
					BoxedValue,
				};
			protected:
				ValueType						valueType;
				DescriptableObject*				rawPtr;
				Ptr<DescriptableObject>			sharedPtr;
				Ptr<IBoxedValue>				boxedValue;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				ITypeDescriptor*				typeDescriptor;
#endif

				Value(DescriptableObject* value);
				Value(Ptr<DescriptableObject> value);
				Value(Ptr<IBoxedValue> value, ITypeDescriptor* associatedTypeDescriptor);
			public:
				/// <summary>Create a null value.</summary>
				Value();
				Value(const Value& value);
				Value&							operator=(const Value& value);

				friend std::partial_ordering	operator<=>(const Value& a, const Value& b);
				friend bool						operator==(const Value& a, const Value& b) { return (a <=> b) == 0; }

				/// <summary>Find out how the value is stored.</summary>
				/// <returns>Returns How the value is stored.</returns>
				ValueType						GetValueType()const;
				/// <summary>Get the stored raw pointer if <b>GetValueType()</b> returns <b>RawPtr</b> or <b>SharedPtr</b>.</summary>
				/// <returns>The stored raw pointer. Returns null if failed.</returns>
				DescriptableObject*				GetRawPtr()const;
				/// <summary>Get the stored shared pointer if <b>GetValueType()</b> returns <b>SharedPtr</b>.</summary>
				/// <returns>The stored shared pointer. Returns null if failed.</returns>
				Ptr<DescriptableObject>			GetSharedPtr()const;
				/// <summary>Get the stored value if <b>GetValueType()</b> returns <b>BoxedValue</b>.</summary>
				/// <returns>The stored text. Returns empty if failed.</returns>
				Ptr<IBoxedValue>				GetBoxedValue()const;
				/// <summary>Test if this value isnull.</summary>
				/// <returns>Returns true if this value is null.</returns>
				bool							IsNull()const;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				/// <summary>Get the real type of the stored object.</summary>
				/// <returns>The real type. Returns null if the value is null.</returns>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				ITypeDescriptor*				GetTypeDescriptor()const;
				WString							GetTypeFriendlyName()const;
				bool							CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const;
				bool							CanConvertTo(ITypeInfo* targetType)const;
#endif

				/// <summary>Create a value from a raw pointer.</summary>
				/// <returns>The created value.</returns>
				/// <param name="value">The raw pointer to store.</param>
				static Value					From(DescriptableObject* value);
				/// <summary>Create a value from a shared pointer.</summary>
				/// <returns>The created value.</returns>
				/// <param name="value">The shared pointer to store.</param>
				static Value					From(Ptr<DescriptableObject> value);
				/// <summary>Create a boxed value.</summary>
				/// <returns>The created value.</returns>
				/// <param name="value">The boxed value to store.</param>
				/// <param name="type">The type of the boxed value.</param>
				static Value					From(Ptr<IBoxedValue> value, ITypeDescriptor* type);

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				static IMethodInfo*				SelectMethod(IMethodGroupInfo* methodGroup, collections::Array<Value>& arguments);

				/// <summary>Call the default constructor of the specified type to create a value.</summary>
				/// <returns>The created value.</returns>
				/// <param name="type">The type to create the value.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				static Value					Create(ITypeDescriptor* type);

				/// <summary>Call the constructor of the specified type to create a value.</summary>
				/// <returns>The created value.</returns>
				/// <param name="type">The type to create the value.</param>
				/// <param name="arguments">Arguments for the constructor.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     public:
				///         MyClass()
				///             :data(L"Hello, world!")
				///         {
				///         }
				/// 
				///         MyClass(const WString& _data)
				///             :data(_data)
				///         {
				///         }
				/// 
				///         WString data;
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(const WString&), { L"data" })
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto myClass = Value::Create(GetTypeDescriptor(L"mynamespace::MyClass"), (Value_xs(), WString(L"Hello, world!!!")));
				/// 
				///         auto ptrMyClass1 = UnboxValue<Ptr<MyClass>>(myClass);
				///         Console::WriteLine(ptrMyClass1->data);
				/// 
				///         Ptr<MyClass> ptrMyClass2;
				///         UnboxParameter(myClass, ptrMyClass2);
				///         Console::WriteLine(ptrMyClass2->data);
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				static Value					Create(ITypeDescriptor* type, collections::Array<Value>& arguments);

				/// <summary>Call the default constructor of the specified type to create a value.</summary>
				/// <returns>The created value.</returns>
				/// <param name="typeName">The registered full name for the type to create the value.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				static Value					Create(const WString& typeName);

				/// <summary>Call the constructor of the specified type to create a value.</summary>
				/// <returns>The created value.</returns>
				/// <param name="typeName">The registered full name for the type to create the value.</param>
				/// <param name="arguments">Arguments for the constructor.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     public:
				///         MyClass()
				///             :data(L"Hello, world!")
				///         {
				///         }
				/// 
				///         MyClass(const WString& _data)
				///             :data(_data)
				///         {
				///         }
				/// 
				///         WString data;
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(const WString&), { L"data" })
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto myClass = Value::Create(L"mynamespace::MyClass", (Value_xs(), WString(L"Hello, world!!!")));
				/// 
				///         auto ptrMyClass1 = UnboxValue<Ptr<MyClass>>(myClass);
				///         Console::WriteLine(ptrMyClass1->data);
				/// 
				///         Ptr<MyClass> ptrMyClass2;
				///         UnboxParameter(myClass, ptrMyClass2);
				///         Console::WriteLine(ptrMyClass2->data);
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				static Value					Create(const WString& typeName, collections::Array<Value>& arguments);

				/// <summary>Call a static method of the specified type.</summary>
				/// <returns>The return value from that method.</returns>
				/// <param name="typeName">The registered full name for the type.</param>
				/// <param name="name">The registered name for the method.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				static Value					InvokeStatic(const WString& typeName, const WString& name);

				/// <summary>Call a static method of the specified type.</summary>
				/// <returns>The return value from that method.</returns>
				/// <param name="typeName">The registered full name for the type.</param>
				/// <param name="name">The registered name for the method.</param>
				/// <param name="arguments">Arguments for the method.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     public:
				///         static void PrintHelloWorld(const WString& name)
				///         {
				///             Console::WriteLine(L"Hello, " + name + L"!");
				///         }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_STATIC_METHOD(PrintHelloWorld, { L"name" })
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         Value::InvokeStatic(L"mynamespace::MyClass", L"PrintHelloWorld", (Value_xs(), WString(L"Gaclib")));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				static Value					InvokeStatic(const WString& typeName, const WString& name, collections::Array<Value>& arguments);

				/// <summary>Call the getter function for a property.</summary>
				/// <returns>The value of the property.</returns>
				/// <param name="name">The registered name for the property.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     private:
				///         WString prop;
				///     public:
				///         WString field;
				/// 
				///         WString GetProp() { return prop; };
				///         void SetProp(const WString& value) { prop = value; }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_FIELD(field)
				///                 CLASS_MEMBER_PROPERTY_FAST(Prop)
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto td = GetTypeDescriptor(L"mynamespace::MyClass");
				///         auto myClass = Value::Create(td);
				/// 
				///         myClass.SetProperty(L"field", BoxValue<WString>(L"Hello, world!"));
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Hello, Gaclib!"));
				/// 
				///         Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"field")));
				///         Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"Prop")));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				Value							GetProperty(const WString& name)const;

				/// <summary>Call the setter function for a property.</summary>
				/// <param name="name">The registered name for the property.</param>
				/// <param name="newValue">The value to set the property.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     private:
				///         WString prop;
				///     public:
				///         WString field;
				/// 
				///         WString GetProp() { return prop; };
				///         void SetProp(const WString& value) { prop = value; }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_FIELD(field)
				///                 CLASS_MEMBER_PROPERTY_FAST(Prop)
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto td = GetTypeDescriptor(L"mynamespace::MyClass");
				///         auto myClass = Value::Create(td);
				/// 
				///         myClass.SetProperty(L"field", BoxValue<WString>(L"Hello, world!"));
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Hello, Gaclib!"));
				/// 
				///         Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"field")));
				///         Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"Prop")));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				void							SetProperty(const WString& name, const Value& newValue);

				/// <summary>Call a non-static method.</summary>
				/// <returns>The return value from that method.</returns>
				/// <param name="name">The registered name for the method.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				Value							Invoke(const WString& name)const;

				/// <summary>Call a non-static method.</summary>
				/// <returns>The return value from that method.</returns>
				/// <param name="name">The registered name for the method.</param>
				/// <param name="arguments">Arguments for the method.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     public:
				///         void PrintHelloWorld(const WString& name)
				///         {
				///             Console::WriteLine(L"Hello, " + name + L"!");
				///         }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_METHOD(PrintHelloWorld, { L"name" })
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto td = GetTypeDescriptor(L"mynamespace::MyClass");
				///         auto myClass = Value::Create(td);
				///         myClass.Invoke(L"PrintHelloWorld", (Value_xs(), WString(L"Gaclib")));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				Value							Invoke(const WString& name, collections::Array<Value>& arguments)const;

				/// <summary>Attach a callback function for the event.</summary>
				/// <returns>The event handler for this attachment. You need to keep it to detach the callback function.</returns>
				/// <param name="name">The registered name for the event.</param>
				/// <param name="function">The callback function.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     private:
				///         WString prop;
				///     public:
				///         Event<void(const WString&, const WString&)> PropChanged;
				/// 
				///         WString GetProp()
				///         {
				///             return prop;
				///         }
				/// 
				///         void SetProp(const WString& value)
				///         {
				///             if (prop != value)
				///             {
				///                 auto old = prop;
				///                 prop = value;
				///                 PropChanged(old, prop);
				///             }
				///         }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_EVENT(PropChanged)
				///                 CLASS_MEMBER_PROPERTY_EVENT_FAST(Prop, PropChanged)
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto td = GetTypeDescriptor(L"mynamespace::MyClass");
				///         auto myClass = Value::Create(td);
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Zero"));
				/// 
				///         using CallbackType = Func<void(const WString&, const WString&)>;
				///         CallbackType callbackFunction = [](const WString& oldProp, const WString& newProp)
				///         {
				///             Console::WriteLine(L"myClass.Prop changed: " + oldProp + L" -> " + newProp);
				///         };
				///         auto handler = myClass.AttachEvent(L"PropChanged", BoxParameter(callbackFunction));
				/// 
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"One"));
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Two"));
				///         myClass.DetachEvent(L"PropChanged", handler);
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Three"));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				Ptr<IEventHandler>				AttachEvent(const WString& name, const Value& function)const;

				/// <summary>Detach a callback function from the event.</summary>
				/// <returns>Returns true if this operation succeeded.</returns>
				/// <param name="name">The registered name for the event.</param>
				/// <param name="handler">The event handler returned from <see cref="AttachEvent"/>.</param>
				/// <remarks>
				/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
				/// </remarks>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class MyClass : public Object, public Description<MyClass>
				///     {
				///     private:
				///         WString prop;
				///     public:
				///         Event<void(const WString&, const WString&)> PropChanged;
				/// 
				///         WString GetProp()
				///         {
				///             return prop;
				///         }
				/// 
				///         void SetProp(const WString& value)
				///         {
				///             if (prop != value)
				///             {
				///                 auto old = prop;
				///                 prop = value;
				///                 PropChanged(old, prop);
				///             }
				///         }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::MyClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(MyClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
				///                 CLASS_MEMBER_EVENT(PropChanged)
				///                 CLASS_MEMBER_PROPERTY_EVENT_FAST(Prop, PropChanged)
				///             END_CLASS_MEMBER(MyClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto td = GetTypeDescriptor(L"mynamespace::MyClass");
				///         auto myClass = Value::Create(td);
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Zero"));
				/// 
				///         using CallbackType = Func<void(const WString&, const WString&)>;
				///         CallbackType callbackFunction = [](const WString& oldProp, const WString& newProp)
				///         {
				///             Console::WriteLine(L"myClass.Prop changed: " + oldProp + L" -> " + newProp);
				///         };
				///         auto handler = myClass.AttachEvent(L"PropChanged", BoxParameter(callbackFunction));
				/// 
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"One"));
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Two"));
				///         myClass.DetachEvent(L"PropChanged", handler);
				///         myClass.SetProperty(L"Prop", BoxValue<WString>(L"Three"));
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				bool							DetachEvent(const WString& name, Ptr<IEventHandler> handler)const;
#endif

				/// <summary>Dispose the object if <b>GetValueType()</b> returns <b>RawPtr</b>.</summary>
				/// <returns>
				/// Returns true if the object is disposed.
				/// Returns false if the object cannot be disposed.
				/// An exception will be thrown if the reference counter is not 0.
				///</returns>
				/// <example><![CDATA[
				/// // reflectable C++ types
				/// 
				/// namespace mynamespace
				/// {
				///     class SharedClass : public Object, public Description<SharedClass>
				///     {
				///     public:
				///         SharedClass()
				///         {
				///             Console::WriteLine(L"SharedClass::SharedClass()");
				///         }
				/// 
				///         ~SharedClass()
				///         {
				///             Console::WriteLine(L"SharedClass::~SharedClass()");
				///         }
				///     };
				/// 
				///     class RawClass : public Object, public Description<RawClass>
				///     {
				///     public:
				///         RawClass()
				///         {
				///             Console::WriteLine(L"RawClass::RawClass()");
				///         }
				/// 
				///         ~RawClass()
				///         {
				///             Console::WriteLine(L"RawClass::~RawClass()");
				///         }
				///     };
				/// }
				/// 
				/// #define MY_TYPELIST(F)\
				///     F(mynamespace::SharedClass)\
				///     F(mynamespace::RawClass)\
				/// 
				/// // it is recommended to put the content below in a separated header file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             MY_TYPELIST(DECL_TYPE_INFO)
				///         }
				///     }
				/// }
				/// 
				/// // it is recommended to put the content below in a separated cpp file
				/// 
				/// namespace vl
				/// {
				///     namespace reflection
				///     {
				///         namespace description
				///         {
				///             using namespace mynamespace;
				/// 
				/// #define _ ,
				/// 
				///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
				/// 
				///             BEGIN_CLASS_MEMBER(SharedClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<SharedClass>(), NO_PARAMETER)
				///             END_CLASS_MEMBER(SharedClass)
				/// 
				///             BEGIN_CLASS_MEMBER(RawClass)
				///                 CLASS_MEMBER_CONSTRUCTOR(RawClass*(), NO_PARAMETER)
				///             END_CLASS_MEMBER(RawClass)
				/// 
				/// #undef  _
				///         }
				///     }
				/// }
				/// 
				/// class MyTypeLoader : public Object, public ITypeLoader
				/// {
				/// public:
				///     void Load(ITypeManager* manager)
				///     {
				///         MY_TYPELIST(ADD_TYPE_INFO)
				///     }
				/// 
				///     void Unload(ITypeManager* manager)
				///     {
				///     }
				/// };
				/// 
				/// // main function
				/// 
				/// int main()
				/// {
				///     LoadPredefinedTypes();
				///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
				///     GetGlobalTypeManager()->Load();
				///     {
				///         auto sharedClass = Value::Create(L"mynamespace::SharedClass");
				///         auto rawClass = Value::Create(L"mynamespace::RawClass");
				/// 
				///         Console::WriteLine(L"sharedClass is " + WString(sharedClass.GetValueType() == Value::SharedPtr ? L"SharedPtr" : L"RawPtr"));
				///         Console::WriteLine(L"rawClass is " + WString(rawClass.GetValueType() == Value::SharedPtr ? L"SharedPtr" : L"RawPtr"));
				/// 
				///         rawClass.DeleteRawPtr();
				///     }
				///     DestroyGlobalTypeManager();
				/// }
				/// ]]></example>
				bool							DeleteRawPtr();
			};
		}
	}
}

#endif

/***********************************************************************
.\DESCRIPTABLEINTERFACES.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_DESCRIPTABLEINTERFACES
#define VCZH_REFLECTION_DESCRIPTABLEINTERFACES


namespace vl
{
	namespace reflection
	{
		namespace description
		{
			class IValueReadonlyList;

			template<typename T>
			struct TypedValueSerializerProvider;
		}

		namespace description
		{
/***********************************************************************
ValueType
***********************************************************************/

			namespace pbt_selector
			{
				template<PredefinedBoxableType _Value>
				struct SelectorBase { static constexpr PredefinedBoxableType Value = _Value; };

				template<typename T> struct Selector : SelectorBase<PredefinedBoxableType::PBT_Unknown> {};

				template<> struct Selector<vint8_t> : SelectorBase<PredefinedBoxableType::PBT_S8> {};
				template<> struct Selector<vint16_t> : SelectorBase<PredefinedBoxableType::PBT_S16> {};
				template<> struct Selector<vint32_t> : SelectorBase<PredefinedBoxableType::PBT_S32> {};
				template<> struct Selector<vint64_t> : SelectorBase<PredefinedBoxableType::PBT_S64> {};

				template<> struct Selector<vuint8_t> : SelectorBase<PredefinedBoxableType::PBT_U8> {};
				template<> struct Selector<vuint16_t> : SelectorBase<PredefinedBoxableType::PBT_U16> {};
				template<> struct Selector<vuint32_t> : SelectorBase<PredefinedBoxableType::PBT_U32> {};
				template<> struct Selector<vuint64_t> : SelectorBase<PredefinedBoxableType::PBT_U64> {};

				template<> struct Selector<float> : SelectorBase<PredefinedBoxableType::PBT_F32> {};
				template<> struct Selector<double> : SelectorBase<PredefinedBoxableType::PBT_F64> {};

				template<> struct Selector<bool> : SelectorBase<PredefinedBoxableType::PBT_BOOL> {};
				template<> struct Selector<wchar_t> : SelectorBase<PredefinedBoxableType::PBT_WCHAR> {};
				template<> struct Selector<WString> : SelectorBase<PredefinedBoxableType::PBT_STRING> {};
				template<> struct Selector<Locale> : SelectorBase<PredefinedBoxableType::PBT_LOCALE> {};
				template<> struct Selector<DateTime> : SelectorBase<PredefinedBoxableType::PBT_DATETIME> {};
			}

			class IValueType : public virtual IDescriptable, public Description<IValueType>
			{
			public:
				template<typename T>
				class TypedBox : public IBoxedValue
				{
				public:
					T							value;

					TypedBox()
						:value{}
					{
					}

					TypedBox(const T& _value)
						:value(_value)
					{
					}

					PredefinedBoxableType GetBoxableType()override
					{
						return pbt_selector::Selector<T>::Value;
					}

					Ptr<IBoxedValue> Copy()override
					{
						return Ptr(new TypedBox<T>(value));
					}

					CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue)override
					{
						if (auto typedBox = boxedValue.Cast<TypedBox<T>>())
						{
							auto r = value <=> typedBox->value;
							if constexpr (std::is_same_v<decltype(r), std::partial_ordering>)
							{
								if (r == std::partial_ordering::unordered) return IBoxedValue::NotComparable;
							}
							if (r < 0) return IBoxedValue::Smaller;
							if (r > 0) return IBoxedValue::Greater;
							return IBoxedValue::Equal;
						}
						return IBoxedValue::NotComparable;
					}
				};

				virtual Value						CreateDefault() = 0;
			};

			class IEnumType : public virtual IDescriptable, public Description<IEnumType>
			{
			public:
				virtual bool					IsFlagEnum() = 0;
				virtual vint					GetItemCount() = 0;
				virtual WString					GetItemName(vint index) = 0;
				virtual vuint64_t				GetItemValue(vint index) = 0;
				virtual vint					IndexOfItem(WString name) = 0;

				virtual Value					ToEnum(vuint64_t value) = 0;
				virtual vuint64_t				FromEnum(const Value& value) = 0;
			};

			class ISerializableType : public virtual IDescriptable, public Description<ISerializableType>
			{
			public:
				virtual bool					Serialize(const Value& input, WString& output) = 0;
				virtual bool					Deserialize(const WString& input, Value& output) = 0;
			};

/***********************************************************************
ITypeDescriptor (type)
***********************************************************************/

			enum class TypeInfoHint
			{
				Normal,
				LazyList,
				Array,
				List,
				SortedList,
				ObservableList,
				Dictionary,
				NativeCollectionReference,
			};

			class ITypeInfo : public virtual IDescriptable, public Description<ITypeInfo>
			{
			public:
				enum Decorator
				{
					RawPtr,
					SharedPtr,
					Nullable,
					TypeDescriptor,
					Generic,
				};

				virtual Decorator				GetDecorator() = 0;
				virtual TypeInfoHint			GetHint() = 0;
				virtual ITypeInfo*				GetElementType() = 0;
				virtual ITypeDescriptor*		GetTypeDescriptor() = 0;
				virtual vint					GetGenericArgumentCount() = 0;
				virtual ITypeInfo*				GetGenericArgument(vint index) = 0;
				virtual WString					GetTypeFriendlyName() = 0;
			};

/***********************************************************************
ITypeDescriptor (basic)
***********************************************************************/

			class IAttributeInfo : public virtual IDescriptable, public Description<IAttributeInfo>
			{
			public:
				virtual ITypeDescriptor*		GetAttributeType() = 0;
				virtual vint					GetAttributeValueCount() = 0;
				virtual ITypeDescriptor*		GetAttributeValueType(vint index) = 0;
				virtual Value					GetAttributeValue(vint index) = 0;
			};

			class IAttributeBag : public virtual IDescriptable, public Description<IAttributeBag>
			{
			public:
				virtual vint					GetAttributeCount() = 0;
				virtual IAttributeInfo*			GetAttribute(vint index) = 0;
			};

			class IMemberInfo : public virtual IAttributeBag, public Description<IMemberInfo>
			{
			public:
				virtual ITypeDescriptor*		GetOwnerTypeDescriptor()=0;
				virtual const WString&			GetName()=0;
			};

/***********************************************************************
ITypeDescriptor (event)
***********************************************************************/

			class IEventHandler : public virtual IDescriptable, public Description<IEventHandler>
			{
			public:
				virtual bool					IsAttached()=0;
			};

			class IEventInfo : public virtual IMemberInfo, public Description<IEventInfo>
			{
			public:
				class ICpp : public virtual IDescriptable, public Description<ICpp>
				{
				public:
					/*
					Arguments:
						$Name:					Event name
						$This:					Expression for the "this" argument
						$Handler:				Event handler function / Event handler object
						$Arguments:				Expressions for arguments separated by ", "
					Default (for Vlpp Event):
						Attach:					::vl::__vwsn::EventAttach($This->$Name, $Handler)
						Detach:					::vl::__vwsn::EventDetach($This->$Name, $Handler)
						Invoke:					::vl::__vwsn::EventInvoke($This->$Name)($Arguments)

					GetInvokeTemplate() == L"*":
						This event does not exist in C++
					*/
					virtual const WString&		GetAttachTemplate() = 0;
					virtual const WString&		GetDetachTemplate() = 0;
					virtual const WString&		GetInvokeTemplate() = 0;
				};
				/*
				Priority:
					1. Use ICpp
					2. Use Default
				*/
				virtual ICpp*					GetCpp() = 0;

				virtual ITypeInfo*				GetHandlerType()=0;
				virtual vint					GetObservingPropertyCount()=0;
				virtual IPropertyInfo*			GetObservingProperty(vint index)=0;
				virtual Ptr<IEventHandler>		Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)=0;
				virtual bool					Detach(const Value& thisObject, Ptr<IEventHandler> handler)=0;
				virtual void					Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments)=0;
			};

/***********************************************************************
ITypeDescriptor (property)
***********************************************************************/

			class IPropertyInfo : public virtual IMemberInfo, public Description<IPropertyInfo>
			{
			public:
				class ICpp : public virtual IDescriptable, public Description<ICpp>
				{
				public:
					/*
					Arguments:
						$Type:					C++ full type name
						$Name:					Property name
						$This:					Expression for the "this" argument
					Default:
						Struct:					$This.$Name
						Class:					$This->$Name
					Example:
						Token in syntax tree:	$This->$Name.value

					GetReferenceTemplate() == L"*":
						This property does not exist in C++
					*/
					virtual const WString&		GetReferenceTemplate() = 0;
				};
				/*
				Priority:
					1. Use ICpp
					2. Use ICpp from getter and setter
					3. Use default
				*/
				virtual ICpp*					GetCpp() = 0;

				virtual bool					IsReadable()=0;
				virtual bool					IsWritable()=0;
				virtual ITypeInfo*				GetReturn()=0;
				virtual IMethodInfo*			GetGetter()=0;
				virtual IMethodInfo*			GetSetter()=0;
				virtual IEventInfo*				GetValueChangedEvent()=0;
				virtual Value					GetValue(const Value& thisObject)=0;
				virtual void					SetValue(Value& thisObject, const Value& newValue)=0;
			};

/***********************************************************************
ITypeDescriptor (method)
***********************************************************************/

			class IParameterInfo : public virtual IMemberInfo, public Description<IParameterInfo>
			{
			public:
				virtual ITypeInfo*				GetType()=0;
				virtual IMethodInfo*			GetOwnerMethod()=0;
			};

			class IMethodInfo : public virtual IMemberInfo, public Description<IMethodInfo>
			{
			public:
				class ICpp : public virtual IDescriptable, public Description<ICpp>
				{
				public:
					/*
					Arguments:
						$Type:					C++ full type name
						$Func:					C++ function type (e.g. void(int)), object type not included for method
						$Name:					Method name
						$This:					Expression for the "this" argument;
						$Arguments:				Expressions for arguments separated by ", "
					Default:
						Constructor:			new $Type($Arguments)
						Static:					$Type::$Name($Arguments)
						Normal:					$This->$Name($Arguments)
					Example:
						External constructor:	<full-function-name>($Arguments)
						External method:		<full-function-name>($This, $Arguments)
						Renamed method:			$This-><function-name>($Arguments)

					GetInvokeTemplate() == L"*":
						This method does not exist in C++
					*/
					virtual const WString&		GetInvokeTemplate() = 0;
					virtual const WString&		GetClosureTemplate() = 0;
				};
				/*
				Priority:
					1. Use ICpp
					2. Use default
				*/
				virtual ICpp*					GetCpp() = 0;

				virtual IMethodGroupInfo*		GetOwnerMethodGroup()=0;
				virtual IPropertyInfo*			GetOwnerProperty()=0;
				virtual vint					GetParameterCount()=0;
				virtual IParameterInfo*			GetParameter(vint index)=0;
				virtual ITypeInfo*				GetReturn()=0;
				virtual bool					IsStatic()=0;
				virtual void					CheckArguments(collections::Array<Value>& arguments)=0;
				virtual Value					Invoke(const Value& thisObject, collections::Array<Value>& arguments)=0;
				virtual Value					CreateFunctionProxy(const Value& thisObject) = 0;
			};

			class IMethodGroupInfo : public virtual IMemberInfo, public Description<IMethodGroupInfo>
			{
			public:
				virtual vint					GetMethodCount()=0;
				virtual IMethodInfo*			GetMethod(vint index)=0;
			};

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

			enum class TypeDescriptorFlags : vint
			{
				Undefined			= 0,
				Object				= 1<<0,
				IDescriptable		= 1<<1,
				Class				= 1<<2,
				Interface			= 1<<3,
				Primitive			= 1<<4,
				Struct				= 1<<5,
				FlagEnum			= 1<<6,
				NormalEnum			= 1<<7,

				ClassType			= Object | Class,
				InterfaceType		= IDescriptable | Interface,
				ReferenceType		= ClassType | InterfaceType,
				EnumType			= FlagEnum | NormalEnum,
				StructType			= Primitive | Struct,
			};

			inline TypeDescriptorFlags operator&(TypeDescriptorFlags a, TypeDescriptorFlags b)
			{
				return (TypeDescriptorFlags)((vint)a & (vint)b);
			}

			inline TypeDescriptorFlags operator|(TypeDescriptorFlags a, TypeDescriptorFlags b)
			{
				return (TypeDescriptorFlags)((vint)a | (vint)b);
			}

			/// <summary>Metadata class for reflectable types.</summary>
			class ITypeDescriptor : public virtual IAttributeBag, public Description<ITypeDescriptor>
			{
			public:
				class ICpp : public virtual IDescriptable, public Description<ICpp>
				{
				public:
					/*
						Default:				refer to TypeInfoContent::VlppType

						GetFullName() == L"*":
							This type does not exist in C++
					*/
					virtual const WString&		GetFullName() = 0;
				};
				/*
				Priority:
					1. Use ICpp
					2. Use default
				*/
				virtual ICpp*					GetCpp() = 0;

				virtual TypeDescriptorFlags		GetTypeDescriptorFlags() = 0;
				virtual bool					IsAggregatable() = 0;
				virtual const WString&			GetTypeName() = 0;

				virtual IValueType*				GetValueType() = 0;
				virtual IEnumType*				GetEnumType() = 0;
				virtual ISerializableType*		GetSerializableType() = 0;

				virtual vint					GetBaseTypeDescriptorCount() = 0;
				virtual ITypeDescriptor*		GetBaseTypeDescriptor(vint index) = 0;
				virtual bool					CanConvertTo(ITypeDescriptor* targetType) = 0;

				virtual vint					GetPropertyCount() = 0;
				virtual IPropertyInfo*			GetProperty(vint index) = 0;
				virtual bool					IsPropertyExists(const WString& name, bool inheritable) = 0;
				virtual IPropertyInfo*			GetPropertyByName(const WString& name, bool inheritable) = 0;

				virtual vint					GetEventCount() = 0;
				virtual IEventInfo*				GetEvent(vint index) = 0;
				virtual bool					IsEventExists(const WString& name, bool inheritable) = 0;
				virtual IEventInfo*				GetEventByName(const WString& name, bool inheritable) = 0;

				virtual vint					GetMethodGroupCount() = 0;
				virtual IMethodGroupInfo*		GetMethodGroup(vint index) = 0;
				virtual bool					IsMethodGroupExists(const WString& name, bool inheritable) = 0;
				virtual IMethodGroupInfo*		GetMethodGroupByName(const WString& name, bool inheritable) = 0;
				virtual IMethodGroupInfo*		GetConstructorGroup() = 0;
			};

#ifndef VCZH_DEBUG_NO_REFLECTION

/***********************************************************************
ITypeManager
***********************************************************************/

			class ITypeManager;

			/// <summary>Delay loading for registering reflectable types.</summary>
			class ITypeLoader : public virtual Interface
			{
			public:
				/// <summary>Called when it is time to register types.</summary>
				/// <param name="manager">The type manager.</param>
				virtual void					Load(ITypeManager* manager)=0;

				/// <summary>Called when it is time to unregister types.</summary>
				/// <param name="manager">The type manager.</param>
				/// <remarks>
				/// Types cannot be unregistered one by one,
				/// they are removed at the same time by calling
				/// [F:vl.reflection.description.DestroyGlobalTypeManager] or
				/// [F:vl.reflection.description.ResetGlobalTypeManager].
				/// Here is just a chance for reverse extra steps, when these steps are taken in <see cref="Load"/>.
				/// </remarks>
				virtual void					Unload(ITypeManager* manager)=0;
			};

			/// <summary>A type manager to access all reflectable types.</summary>
			class ITypeManager : public virtual Interface
			{
			public:
				/// <summary>Get the number of all registered types.</summary>
				/// <returns>The number of all registered types.</returns>
				virtual vint					GetTypeDescriptorCount()=0;

				/// <summary>Get one registered type.</summary>
				/// <returns>A registered type specified by the index.</returns>
				/// <param name="index">The index for retriving the registered type.</param>
				/// <remarks>
				/// The index itself does not has any specific meaning.
				/// And it is no guarantee that an index will always return the same type for each execution of the same process.
				/// </remarks>
				virtual ITypeDescriptor*		GetTypeDescriptor(vint index)=0;
				virtual ITypeDescriptor*		GetTypeDescriptor(const WString& name)=0;
				virtual bool					SetTypeDescriptor(const WString& name, Ptr<ITypeDescriptor> typeDescriptor)=0;

				/// <summary>Delay register some types.</summary>
				/// <returns>Returns true if this operation succeeded.</returns>
				/// <param name="typeLoader">A type loader for delay registering.</param>
				/// <remarks>
				/// You can still call this function after <see cref="Load"/> is called.
				/// In this case, there is no delay registering, all types in this loader will be registered immediately.
				/// </remarks>
				virtual bool					AddTypeLoader(Ptr<ITypeLoader> typeLoader)=0;
				virtual bool					RemoveTypeLoader(Ptr<ITypeLoader> typeLoader)=0;

				/// <summary>Load all added type loaders.</summary>
				/// <returns>Returns true if this operation succeeded.</returns>
				virtual bool					Load()=0;
				virtual bool					Unload()=0;
				virtual bool					Reload()=0;
				virtual bool					IsLoaded()=0;
				virtual ITypeDescriptor*		GetRootType()=0;
				virtual vint					GetTypeVersion()=0;
			};

			/// <summary>Get the type manager.</summary>
			/// <returns>Returns the type manager.</returns>
			extern ITypeManager*				GetGlobalTypeManager();

			/// <summary>Unload all types and free the type manager.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <remarks>
			/// After calling this function, you can no longer register new types,
			/// and calling <see cref="GetGlobalTypeManager"/> will always get null.
			/// </remarks>

			extern bool							DestroyGlobalTypeManager();

			/// <summary>Unload all types and reset the type manager.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			/// <remarks>
			/// <p>
			/// This function is similar to <see cref="DestroyGlobalTypeManager"/>,
			/// but calling this function allows types to be registsred again.
			/// </p>
			/// <p>
			/// This function is very useful for unit testing.
			/// In each test case, you can first register all types,
			/// and after the test case is finished, call this function to reset all types.
			/// You can do this again and again in the other test cases,
			/// so that these test cases don't affect each other.
			/// </p>
			/// </remarks>
			extern bool							ResetGlobalTypeManager();

			/// <summary>Get a registered type given the registered name.</summary>
			/// <returns>Returns the metadata class for this registered type.</returns>
			/// <param name="name">
			/// The registered name.
			/// Note that this is not the full name of the C++ type,
			/// it is the name what is used to registere this type.</param>
			/// <remarks>
			/// Returning null means the type registration is declared but the type manager has not started.
			/// </remarks>
			extern ITypeDescriptor*				GetTypeDescriptor(const WString& name);
			extern bool							IsInterfaceType(ITypeDescriptor* typeDescriptor, bool& acceptProxy);
			extern void							LogTypeManager(stream::TextWriter& writer);
			extern void							GenerateMetaonlyTypes(stream::IStream& outputStream);
			extern Ptr<ITypeLoader>				LoadMetaonlyTypes(stream::IStream& inputStream, const collections::Dictionary<WString, Ptr<ISerializableType>>& serializableTypes);

/***********************************************************************
Cpp Helper Functions
***********************************************************************/

			extern WString						CppGetFullName(ITypeDescriptor* type);
			extern WString						CppGetReferenceTemplate(IPropertyInfo* prop);
			extern WString						CppGetClosureTemplate(IMethodInfo* method);
			extern WString						CppGetInvokeTemplate(IMethodInfo* method);
			extern WString						CppGetAttachTemplate(IEventInfo* ev);
			extern WString						CppGetDetachTemplate(IEventInfo* ev);
			extern WString						CppGetInvokeTemplate(IEventInfo* ev);

			extern bool							CppExists(ITypeDescriptor* type);
			extern bool							CppExists(IPropertyInfo* prop);
			extern bool							CppExists(IMethodInfo* method);
			extern bool							CppExists(IEventInfo* ev);

#endif

/***********************************************************************
Exceptions
***********************************************************************/

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

			class TypeNotExistsException : public TypeDescriptorException
			{
			public:
				TypeNotExistsException(const WString& name)
					:TypeDescriptorException(L"Cannot find the type \""+name+L"\".")
				{
				}
			};

			class ConstructorNotExistsException : public TypeDescriptorException
			{
			public:
				ConstructorNotExistsException(ITypeDescriptor* type)
					:TypeDescriptorException(L"Cannot find any constructor in type \"" + type->GetTypeName() + L"\".")
				{
				}
			};

			class MemberNotExistsException : public TypeDescriptorException
			{
			public:
				MemberNotExistsException(const WString& name, ITypeDescriptor* type)
					:TypeDescriptorException(L"Cannot find the member \"" + name + L"\" in type \"" + type->GetTypeName() + L"\".")
				{
				}
			};

			class PropertyIsNotReadableException : public TypeDescriptorException
			{
			public:
				PropertyIsNotReadableException(IPropertyInfo* propertyInfo)
					:TypeDescriptorException(L"Cannot read value from a property \"" + propertyInfo->GetName() + L"\" that is not readable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}
			};

			class PropertyIsNotWritableException : public TypeDescriptorException
			{
			public:
				PropertyIsNotWritableException(IPropertyInfo* propertyInfo)
					:TypeDescriptorException(L"Cannot write value to a property \"" + propertyInfo->GetName() + L"\" that is not writable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}
			};

			class ArgumentNullException : public TypeDescriptorException
			{
			public:
				ArgumentNullException(const WString& name, const WString& member)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing its member \"" + member + L"\".")
				{
				}

				ArgumentNullException(const WString& name, IMethodInfo* target)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}

				ArgumentNullException(const WString& name, IEventInfo* target)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing event \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}

				ArgumentNullException(const WString& name, IPropertyInfo* target)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking property \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}
			};

			class ArgumentTypeMismtatchException : public TypeDescriptorException
			{
			public:
				ArgumentTypeMismtatchException(const WString& name, ITypeDescriptor* expected, ITypeDescriptor* actual)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual->GetTypeName() + L"\" to \"" + expected->GetTypeName() + L"\".")
				{
				}

				ArgumentTypeMismtatchException(const WString& name, ITypeInfo* expected, const Value& actual)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" + expected->GetTypeFriendlyName() + L"\".")
				{
				}

				ArgumentTypeMismtatchException(const WString& name, ITypeDescriptor* type, Value::ValueType valueType, const Value& actual)
					:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" +
						(valueType == Value::SharedPtr ? L"Ptr<" : L"") + type->GetTypeName() + (valueType == Value::SharedPtr ? L">" : valueType == Value::RawPtr ? L"*" : L"")
						+ L"\".")
				{
				}
			};

			class ArgumentCountMismtatchException : public TypeDescriptorException
			{
			public:
				ArgumentCountMismtatchException()
					:TypeDescriptorException(L"Argument count does not match the definition.")
				{
				}

				ArgumentCountMismtatchException(IMethodGroupInfo* target)
					:TypeDescriptorException(L"Argument count does not match the definition when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
				{
				}
			};

#endif
		}
	}
}

#endif

/***********************************************************************
.\PREDEFINED\OBSERVABLELIST.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_TYPES_OBSERVABLELIST
#define VCZH_REFLECTION_TYPES_OBSERVABLELIST
 
 
namespace vl
{
	namespace collections
	{
		/// <summary>Base type of observable container which triggers callbacks whenever items are changed.</summary>
		/// <typeparam name="T">Type of elements.</typeparam>
		/// <remarks>
		/// <p>Methods are the same to <see cref="List`2"/>, except that operator[] is readonly.</p>
		/// <p>
		/// When an item is being inserted to the list,
		/// <b>QueryInsert</b> will be called to determine if this item can be inserted,
		/// <b>BeforeInsert</b> will be called before inserting,
		/// <b>AfterInsert</b> will be called after inserting.
		/// </p>
		/// <p>
		/// When an item is being removed from the list,
		/// <b>QueryRemove</b> will be called to determine if this item can be removed,
		/// <b>BeforeRemove</b> will be called before removing,
		/// <b>AfterRemove</b> will be called after removing.
		/// </p>
		/// <p>
		/// When an item is being replaced, it is considered as removing the original item and inserting the new item.
		/// </p>
		/// <p>
		/// After any changing happens, <b>NotifyUpdateInternal</b> is called.
		/// Arguments is exactly the same as <see cref="reflection::description::IValueObservableList::ItemChanged"/>.
		/// </p>
		/// </remarks>
		template<typename T>
		class ObservableListBase : public collections::EnumerableBase<T>
		{
			using K = typename KeyType<T>::Type;
		protected:
			collections::List<T>					items;

			virtual void NotifyUpdateInternal(vint start, vint count, vint newCount)
			{
			}

			virtual bool QueryInsert(vint index, const T& value)
			{
				return true;
			}

			virtual void BeforeInsert(vint index, const T& value)
			{
			}

			virtual void AfterInsert(vint index, const T& value)
			{
			}

			virtual bool QueryRemove(vint index, const T& value)
			{
				return true;
			}

			virtual void BeforeRemove(vint index, const T& value)
			{
			}

			virtual void AfterRemove(vint index, vint count)
			{
			}

		public:
			collections::IEnumerator<T>* CreateEnumerator()const
			{
				return items.CreateEnumerator();
			}

			/// <summary>Trigger <b>NotifyUpdateInternal</b> manually.</summary>
			/// <returns>Returns true if arguments are not out of range.</returns>
			/// <param name="start">The index of the first item that are changed.</param>
			/// <param name="count">The number of items that are changed, the default value is 1.</param>
			/// <remarks>
			/// <p>
			/// This is useful when the container is not actually changed, but data in some items are changed.
			/// For example, in an observable list of shared pointers,
			/// properties of elements are changed does not trigger callbacks because it doesn't change pointers in the list.
			/// </p>
			/// <p>
			/// If subscribers need to know about such change, calling this function is an easy way to do it.
			/// </p>
			/// </remarks>
			bool NotifyUpdate(vint start, vint count = 1)
			{
				if (start<0 || start >= items.Count() || count <= 0 || start + count>items.Count())
				{
					return false;
				}
				else
				{
					NotifyUpdateInternal(start, count, count);
					return true;
				}
			}

			bool Contains(const K& item)const
			{
				return items.Contains(item);
			}

			vint Count()const
			{
				return items.Count();
			}

			vint Count()
			{
				return items.Count();
			}

			const T& Get(vint index)const
			{
				return items.Get(index);
			}

			const T& operator[](vint index)const
			{
				return items.Get(index);
			}

			vint IndexOf(const K& item)const
			{
				return items.IndexOf(item);
			}

			vint Add(const T& item)
			{
				return Insert(items.Count(), item);
			}

			bool Remove(const K& item)
			{
				vint index = items.IndexOf(item);
				if (index == -1) return false;
				return RemoveAt(index);
			}

			bool RemoveAt(vint index)
			{
				if (0 <= index && index < items.Count() && QueryRemove(index, items[index]))
				{
					BeforeRemove(index, items[index]);
					T item = items[index];
					items.RemoveAt(index);
					AfterRemove(index, 1);
					NotifyUpdateInternal(index, 1, 0);
					return true;
				}
				return false;
			}

			bool RemoveRange(vint index, vint count)
			{
				if (count <= 0) return false;
				if (0 <= index && index<items.Count() && index + count <= items.Count())
				{
					for (vint i = 0; i < count; i++)
					{
						if (!QueryRemove(index + 1, items[index + i])) return false;
					}
					for (vint i = 0; i < count; i++)
					{
						BeforeRemove(index + i, items[index + i]);
					}
					items.RemoveRange(index, count);
					AfterRemove(index, count);
					NotifyUpdateInternal(index, count, 0);
					return true;
				}
				return false;
			}

			bool Clear()
			{
				vint count = items.Count();
				for (vint i = 0; i < count; i++)
				{
					if (!QueryRemove(i, items[i])) return false;
				}
				for (vint i = 0; i < count; i++)
				{
					BeforeRemove(i, items[i]);
				}
				items.Clear();
				AfterRemove(0, count);
				NotifyUpdateInternal(0, count, 0);
				return true;
			}

			vint Insert(vint index, const T& item)
			{
				if (0 <= index && index <= items.Count() && QueryInsert(index, item))
				{
					BeforeInsert(index, item);
					items.Insert(index, item);
					AfterInsert(index, item);
					NotifyUpdateInternal(index, 0, 1);
					return index;
				}
				else
				{
					return -1;
				}
			}

			bool Set(vint index, const T& item)
			{
				if (0 <= index && index < items.Count())
				{
					if (QueryRemove(index, items[index]) && QueryInsert(index, item))
					{
						BeforeRemove(index, items[index]);
						items.RemoveAt(index);
						AfterRemove(index, 1);

						BeforeInsert(index, item);
						items.Insert(index, item);
						AfterInsert(index, item);

						NotifyUpdateInternal(index, 1, 1);
						return true;
					}
				}
				return false;
			}
		};

		/// <summary>An observable container that maintain an implementation of <see cref="reflection::description::IValueObservableList"/>.</summary>
		/// <typeparam name="T">Type of elements.</typeparam>
		template<typename T>
		class ObservableList : public ObservableListBase<T>
		{
		protected:
			void NotifyUpdateInternal(vint start, vint count, vint newCount) override;

		public:
		};

		namespace randomaccess_internal
		{
			template<typename T>
			struct RandomAccessable<ObservableListBase<T>>
			{
				static const bool							CanRead = true;
				static const bool							CanResize = false;
			};

			template<typename T>
			struct RandomAccessable<ObservableList<T>>
			{
				static const bool							CanRead = true;
				static const bool							CanResize = false;
			};
		}
	}
}

#endif

/***********************************************************************
.\PREDEFINED\TYPEDVALUESERIALIZERPROVIDER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_TYPES_TYPEDVALUESERIALIZERPROVIDER
#define VCZH_REFLECTION_TYPES_TYPEDVALUESERIALIZERPROVIDER

#include <limits.h>
#include <float.h>

namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
Constants
***********************************************************************/

			template<typename T>
			struct TypedValueSerializerMinMax;

			template<>
			struct TypedValueSerializerMinMax<vint8_t>
			{
				static constexpr vint8_t Min = _I8_MIN;
				static constexpr vint8_t Max = _I8_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vint16_t>
			{
				static constexpr vint16_t Min = _I16_MIN;
				static constexpr vint16_t Max = _I16_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vint32_t>
			{
				static constexpr vint32_t Min = _I32_MIN;
				static constexpr vint32_t Max = _I32_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vint64_t>
			{
				static constexpr vint64_t Min = _I64_MIN;
				static constexpr vint64_t Max = _I64_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vuint8_t>
			{
				static constexpr vuint8_t Min = 0;
				static constexpr vuint8_t Max = _UI8_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vuint16_t>
			{
				static constexpr vuint16_t Min = 0;
				static constexpr vuint16_t Max = _UI16_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vuint32_t>
			{
				static constexpr vuint32_t Min = 0;
				static constexpr vuint32_t Max = _UI32_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<vuint64_t>
			{
				static constexpr vuint64_t Min = 0;
				static constexpr vuint64_t Max = _UI64_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<float>
			{
				static constexpr float Min = (float)-FLT_MAX;
				static constexpr float Max = (float)FLT_MAX;
			};

			template<>
			struct TypedValueSerializerMinMax<double>
			{
				static constexpr double Min = (double)-DBL_MAX;
				static constexpr double Max = (double)DBL_MAX;
			};

/***********************************************************************
Signed Types
***********************************************************************/

			template<typename T>
			struct TypedValueSerializerProvider_Signed
			{
				static T GetDefaultValue()
				{
					return 0;
				}

				static bool Serialize(const T& input, WString& output)
				{
					output = i64tow(input);
					return true;
				}

				static bool Deserialize(const WString& input, T& output)
				{
					constexpr T MinValue = TypedValueSerializerMinMax<T>::Min;
					constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
					bool success = false;
					vint64_t result = wtoi64_test(input, success);
					if (!success) return false;
					if (result < MinValue || result > MaxValue) return false;
					output = (T)result;
					return true;
				}
			};

/***********************************************************************
Unsigned Types
***********************************************************************/

			template<typename T>
			struct TypedValueSerializerProvider_Unsigned
			{
				static T GetDefaultValue()
				{
					return 0;
				}

				static bool Serialize(const T& input, WString& output)
				{
					output = u64tow(input);
					return true;
				}

				static bool Deserialize(const WString& input, T& output)
				{
					constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
					bool success = false;
					vuint64_t result = wtou64_test(input, success);
					if (!success) return false;
					if (result > MaxValue) return false;
					output = (T)result;
					return true;
				}
			};

/***********************************************************************
Floating Point Types
***********************************************************************/

			template<typename T>
			struct TypedValueSerializerProvider_FloatingPoint
			{
				static T GetDefaultValue()
				{
					return 0;
				}

				static bool Serialize(const T& input, WString& output)
				{
					output = ftow(input);
					if (output == L"-0") output = L"0";
					return true;
				}

				static bool Deserialize(const WString& input, T& output)
				{
					constexpr T MinValue = TypedValueSerializerMinMax<T>::Min;
					constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
					bool success = false;
					double result = wtof_test(input, success);
					if (!success) return false;
					if (result < MinValue || result > MaxValue) return false;
					output = (T)result;
					return true;
				}
			};

/***********************************************************************
Serializable Types
***********************************************************************/

#define DEFINE_SIGNED_TVSP(TYPENAME)\
		template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_Signed<TYPENAME> {};\

		DEFINE_SIGNED_TVSP(vint8_t)
		DEFINE_SIGNED_TVSP(vint16_t)
		DEFINE_SIGNED_TVSP(vint32_t)
		DEFINE_SIGNED_TVSP(vint64_t)
#undef DEFINE_SIGNED_TVSP

#define DEFINE_UNSIGNED_TVSP(TYPENAME)\
		template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_Unsigned<TYPENAME> {};\

		DEFINE_UNSIGNED_TVSP(vuint8_t)
		DEFINE_UNSIGNED_TVSP(vuint16_t)
		DEFINE_UNSIGNED_TVSP(vuint32_t)
		DEFINE_UNSIGNED_TVSP(vuint64_t)
#undef DEFINE_UNSIGNED_TVSP

#define DEFINE_FLOAT_TVSP(TYPENAME)\
		template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_FloatingPoint<TYPENAME> {};\

		DEFINE_FLOAT_TVSP(float)
		DEFINE_FLOAT_TVSP(double)
#undef DEFINE_FLOAT_TVSP
			
#define DEFINE_TVSP(TYPENAME)\
			template<>\
			struct TypedValueSerializerProvider<TYPENAME>\
			{\
				static TYPENAME GetDefaultValue();\
				static bool Serialize(const TYPENAME& input, WString& output);\
				static bool Deserialize(const WString& input, TYPENAME& output);\
			};\

		DEFINE_TVSP(bool)
		DEFINE_TVSP(wchar_t)
		DEFINE_TVSP(WString)
		DEFINE_TVSP(Locale)
		DEFINE_TVSP(DateTime)

#undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER
		}
	}
}

#endif


/***********************************************************************
.\PREDEFINED\PREDEFINEDTYPES.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_TYPES_PREDEFINEDTYPES
#define VCZH_REFLECTION_TYPES_PREDEFINEDTYPES

#include <math.h>

namespace vl
{
	namespace reflection
	{
		namespace description
		{
			struct VoidValue {};

/***********************************************************************
Collections
***********************************************************************/

			/// <summary>The reflectable version of <see cref="collections::IEnumerator`1"/>.</summary>
			class IValueEnumerator : public virtual IDescriptable, public Description<IValueEnumerator>
			{
			public:
				/// <summary>Get the reference to the current value in the enumerator.</summary>
				/// <returns>The current value.</returns>
				/// <remarks><see cref="Next"/> needs to be called to make the first value available.</remarks>
				virtual Value					GetCurrent() = 0;

				/// <summary>Get the position of the current value in the enumerator.</summary>
				/// <returns>The position of the current value.</returns>
				virtual vint					GetIndex() = 0;

				/// <summary>Prepare for the next value.</summary>
				/// <returns>Returns false if there is no more value.</returns>
				virtual bool					Next() = 0;
			};

			/// <summary>The reflectable version of <see cref="collections::IEnumerable`1"/>.</summary>
			/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from an enumerable.</remarks>
			/// <example><![CDATA[
			/// // reflectable C++ types
			/// 
			/// namespace mynamespace
			/// {
			///     class MyClass : public Object, public Description<MyClass>
			///     {
			///     public:
			///         MyClass(vint _data = 0)
			///             :data(_data)
			///         {
			///         }
			/// 
			///         vint data;
			///     };
			/// }
			/// 
			/// #define MY_TYPELIST(F)\
			///     F(mynamespace::MyClass)\
			/// 
			/// // it is recommended to put the content below in a separated header file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             MY_TYPELIST(DECL_TYPE_INFO)
			///         }
			///     }
			/// }
			/// 
			/// // it is recommended to put the content below in a separated cpp file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             using namespace mynamespace;
			/// 
			/// #define _ ,
			/// 
			///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
			/// 
			///             BEGIN_CLASS_MEMBER(MyClass)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(vint), { L"data" })
			///                 CLASS_MEMBER_FIELD(data)
			///             END_CLASS_MEMBER(MyClass)
			/// 
			/// #undef  _
			///         }
			///     }
			/// }
			/// 
			/// class MyTypeLoader : public Object, public ITypeLoader
			/// {
			/// public:
			///     void Load(ITypeManager* manager)
			///     {
			///         MY_TYPELIST(ADD_TYPE_INFO)
			///     }
			/// 
			///     void Unload(ITypeManager* manager)
			///     {
			///     }
			/// };
			/// 
			/// // main function
			/// 
			/// int main()
			/// {
			///     LoadPredefinedTypes();
			///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
			///     GetGlobalTypeManager()->Load();
			///     {
			///         LazyList<Ptr<MyClass>> cs = Range<vint>(1, 10)
			///             .Select([](vint i)
			///             {
			///                 return Ptr(new MyClass(i));
			///             });
			/// 
			///         Value boxed = BoxParameter(cs);
			///         {
			///             auto enumerable = UnboxValue<Ptr<IValueEnumerable>>(boxed);
			///             auto enumerator = enumerable->CreateEnumerator();
			///             while (enumerator->Next())
			///             {
			///                 Console::Write(itow(UnboxValue<Ptr<MyClass>>(enumerator->GetCurrent())->data) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///         {
			///             auto enumerator = boxed.Invoke(L"CreateEnumerator");
			///             while (UnboxValue<bool>(enumerator.Invoke(L"Next")))
			///             {
			///                 Console::Write(itow(UnboxValue<vint>(enumerator.GetProperty(L"Current").GetProperty(L"data"))) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///     }
			///     DestroyGlobalTypeManager();
			/// }
			/// ]]></example>
			class IValueEnumerable : public virtual IDescriptable, public Description<IValueEnumerable>
			{
			public:
				/// <summary>
				/// Create an enumerator. <see cref="IValueEnumerator::Next"/> should be called before reading the first value.
				/// </summary>
				/// <returns>The enumerator.</returns>
				virtual Ptr<IValueEnumerator>	CreateEnumerator() = 0;

				/// <summary>Get the underlying collection object, which is boxed to be this interface.</summary>
				/// <returns>The underlying collection object, could be nullptr.</returns>
				virtual const Object*			GetCollectionObject() { return nullptr; }

				/// <summary>Create an enumerable from another lazy list.</summary>
				/// <returns>The created enumerable.</returns>
				/// <param name="values">The lazy list to wrap.</param>
				static Ptr<IValueEnumerable>	Create(collections::LazyList<Value> values);
			};

			/// <summary>
			/// The reflectable version of readonly
			/// <see cref="collections::Array`2"/>,
			/// <see cref="collections::List`2"/> or
			/// <see cref="collections::SortedList`2"/>
			/// <see cref="collections::ObservableListBase`2"/>
			/// <see cref="collections::ObservableList`2"/>
			/// </summary>
			class IValueReadonlyList : public virtual IValueEnumerable, public Description<IValueReadonlyList>
			{
			public:
				/// <summary>Get the number of elements in the container.</summary>
				/// <returns>The number of elements.</returns>
				virtual vint					GetCount() = 0;

				/// <summary>Get the reference to the specified element.</summary>
				/// <returns>The reference to the specified element. It will crash when the index is out of range.</returns>
				/// <param name="index">The index of the element.</param>
				virtual Value					Get(vint index) = 0;

				/// <summary>Test does the list contain a value or not.</summary>
				/// <returns>Returns true if the list contains the specified value.</returns>
				/// <param name="value">The value to test.</param>
				virtual bool					Contains(const Value& value) = 0;

				/// <summary>Get the position of a value in this list.</summary>
				/// <returns>Returns the position of first element that equals to the specified value. Returns -1 if failed to find.</returns>
				/// <param name="value">The value to find.</param>
				virtual vint					IndexOf(const Value& value) = 0;
			};

			/// <summary>
			/// The reflectable version of writable
			/// <see cref="collections::Array`2"/>
			/// </summary>
			/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a container.</remarks>
			class IValueArray : public virtual IValueReadonlyList, public Description<IValueArray>
			{
			public:
				/// <summary>Replace an element in the specified position.</summary>
				/// <returns>Returns true if this operation succeeded. It will crash when the index is out of range</returns>
				/// <param name="index">The position of the element to replace.</param>
				/// <param name="value">The new value to replace.</param>
				virtual void					Set(vint index, const Value& value) = 0;

				/// <summary>Append a value at the end of the list.</summary>
				/// <returns>The index of the added item.</returns>
				/// <param name="value">The value to add.</param>
				virtual void					Resize(vint size) = 0;

				/// <summary>Create an empty array.</summary>
				/// <returns>The created list.</returns>
				static Ptr<IValueArray>			Create();

				/// <summary>Create an array with elements copied from another readonly list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueArray>			Create(Ptr<IValueReadonlyList> values);

				/// <summary>Create an array with elements copied from another lazy list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueArray>			Create(collections::LazyList<Value> values);
			};

			/// <summary>
			/// The reflectable version of writable
			/// <see cref="collections::Array`2"/> or
			/// <see cref="collections::List`2"/> or
			/// <see cref="collections::ObservableListBase`2"/>
			/// </summary>
			/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a container.</remarks>
			/// <example><![CDATA[
			/// // reflectable C++ types
			/// 
			/// namespace mynamespace
			/// {
			///     class MyClass : public Object, public Description<MyClass>
			///     {
			///     public:
			///         MyClass(vint _data = 0)
			///             :data(_data)
			///         {
			///         }
			/// 
			///         vint data;
			///     };
			/// }
			/// 
			/// #define MY_TYPELIST(F)\
			///     F(mynamespace::MyClass)\
			/// 
			/// // it is recommended to put the content below in a separated header file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             MY_TYPELIST(DECL_TYPE_INFO)
			///         }
			///     }
			/// }
			/// 
			/// // it is recommended to put the content below in a separated cpp file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             using namespace mynamespace;
			/// 
			/// #define _ ,
			/// 
			///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
			/// 
			///             BEGIN_CLASS_MEMBER(MyClass)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(vint), { L"data" })
			///                 CLASS_MEMBER_FIELD(data)
			///             END_CLASS_MEMBER(MyClass)
			/// 
			/// #undef  _
			///         }
			///     }
			/// }
			/// 
			/// class MyTypeLoader : public Object, public ITypeLoader
			/// {
			/// public:
			///     void Load(ITypeManager* manager)
			///     {
			///         MY_TYPELIST(ADD_TYPE_INFO)
			///     }
			/// 
			///     void Unload(ITypeManager* manager)
			///     {
			///     }
			/// };
			/// 
			/// // main function
			/// 
			/// int main()
			/// {
			///     LoadPredefinedTypes();
			///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
			///     GetGlobalTypeManager()->Load();
			///     {
			///         List<Ptr<MyClass>> cs;
			///         CopyFrom(cs, Range<vint>(1, 10)
			///             .Select([](vint i)
			///             {
			///                 return Ptr(new MyClass(i));
			///             })
			///         );
			/// 
			///         Value boxed = BoxParameter(cs);
			///         {
			///             auto list = UnboxValue<Ptr<IValueList>>(boxed);
			///             for (vint i = 0; i < list->GetCount(); i++)
			///             {
			///                 Console::Write(itow(UnboxValue<Ptr<MyClass>>(list->Get(i))->data) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///
			///         for (vint i = 1; i <= 5; i++)
			///         {
			///             cs.RemoveAt(i);
			///         }
			///
			///         {
			///             for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
			///             {
			///                 Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///     }
			///     DestroyGlobalTypeManager();
			/// }
			/// ]]></example>
			class IValueList : public virtual IValueReadonlyList, public Description<IValueList>
			{
			public:
				/// <summary>Replace an element in the specified position.</summary>
				/// <returns>Returns true if this operation succeeded. It will crash when the index is out of range</returns>
				/// <param name="index">The position of the element to replace.</param>
				/// <param name="value">The new value to replace.</param>
				virtual void					Set(vint index, const Value& value) = 0;

				/// <summary>Append a value at the end of the list.</summary>
				/// <returns>The index of the added item.</returns>
				/// <param name="value">The value to add.</param>
				virtual vint					Add(const Value& value) = 0;

				/// <summary>Insert a value at the specified position.</summary>
				/// <returns>The index of the added item. It will crash if the index is out of range</returns>
				/// <param name="index">The position to insert the value.</param>
				/// <param name="value">The value to add.</param>
				virtual vint					Insert(vint index, const Value& value) = 0;

				/// <summary>Remove an element from the list. If multiple elements equal to the specified value, only the first one will be removed.</summary>
				/// <returns>Returns true if the element is removed.</returns>
				/// <param name="value">The item to remove.</param>
				virtual bool					Remove(const Value& value) = 0;

				/// <summary>Remove an element at a specified position.</summary>
				/// <returns>Returns true if the element is removed. It will crash when the index is out of range.</returns>
				/// <param name="index">The index of the element to remove.</param>
				virtual bool					RemoveAt(vint index) = 0;

				/// <summary>Remove all elements.</summary>
				virtual void					Clear() = 0;

				/// <summary>Create an empty list.</summary>
				/// <returns>The created list.</returns>
				static Ptr<IValueList>			Create();

				/// <summary>Create a list with elements copied from another readonly list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueList>			Create(Ptr<IValueReadonlyList> values);

				/// <summary>Create a list with elements copied from another lazy list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueList>			Create(collections::LazyList<Value> values);
			};

			/// <summary>
			/// The reflectable version of list container which triggers an event whenever items are changed.
			/// </summary>
			/// <example><![CDATA[
			/// // reflectable C++ types
			/// 
			/// namespace mynamespace
			/// {
			///     class MyClass : public Object, public Description<MyClass>
			///     {
			///     public:
			///         MyClass(vint _data = 0)
			///             :data(_data)
			///         {
			///         }
			/// 
			///         vint data;
			///     };
			/// }
			/// 
			/// #define MY_TYPELIST(F)\
			///     F(mynamespace::MyClass)\
			/// 
			/// // it is recommended to put the content below in a separated header file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             MY_TYPELIST(DECL_TYPE_INFO)
			///         }
			///     }
			/// }
			/// 
			/// // it is recommended to put the content below in a separated cpp file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             using namespace mynamespace;
			/// 
			/// #define _ ,
			/// 
			///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
			/// 
			///             BEGIN_CLASS_MEMBER(MyClass)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(vint), { L"data" })
			///                 CLASS_MEMBER_FIELD(data)
			///             END_CLASS_MEMBER(MyClass)
			/// 
			/// #undef  _
			///         }
			///     }
			/// }
			/// 
			/// class MyTypeLoader : public Object, public ITypeLoader
			/// {
			/// public:
			///     void Load(ITypeManager* manager)
			///     {
			///         MY_TYPELIST(ADD_TYPE_INFO)
			///     }
			/// 
			///     void Unload(ITypeManager* manager)
			///     {
			///     }
			/// };
			/// 
			/// // main function
			/// 
			/// int main()
			/// {
			///     LoadPredefinedTypes();
			///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
			///     GetGlobalTypeManager()->Load();
			///     {
			///         ObservableList<Ptr<MyClass>> cs;
			///         CopyFrom(cs, Range<vint>(1, 10)
			///             .Select([](vint i)
			///             {
			///                 return Ptr(new MyClass(i));
			///             })
			///         );
			/// 
			///         Value boxed = BoxParameter(cs);
			///         auto list = UnboxValue<Ptr<IValueObservableList>>(boxed);
			///         {
			///             for (vint i = 0; i < list->GetCount(); i++)
			///             {
			///                 Console::Write(itow(UnboxValue<Ptr<MyClass>>(list->Get(i))->data) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			/// 
			///         {
			///             using CallbackType = Func<void(vint, vint, vint)>;
			///             CallbackType callbackFunction = [](vint index, vint oldCount, vint newCount)
			///             {
			///                 Console::WriteLine(L"ItemChanged(" + itow(index) + L", " + itow(oldCount) + L", " + itow(newCount) + L");");
			///             };
			/// 
			///             auto handler = boxed.AttachEvent(L"ItemChanged", BoxParameter(callbackFunction));
			///             for (vint i = 1; i <= 5; i++)
			///             {
			///                 cs.RemoveAt(i);
			///             }
			///             boxed.DetachEvent(L"ItemChanged", handler);
			///         }
			/// 
			///         {
			///             for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
			///             {
			///                 Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///     }
			///     DestroyGlobalTypeManager();
			/// }
			/// ]]></example>
			class IValueObservableList : public virtual IValueList, public Description<IValueObservableList>
			{
				typedef void ItemChangedProc(vint index, vint oldCount, vint newCount);
			public:
				/// <summary>
				/// <p>Event that is triggered whenever items are changed.</p>
				/// <p>The first argument is the index of the first item that is changed.</p>
				/// <p>The second argument is the number of original items that are replaced by new items.</p>
				/// <p>The third argument is the number of new items that replace original items.</p>
				/// </summary>
				/// <remarks>
				/// <p>If an item is changed, oldCount and newCount are both 1.</p>
				/// <p>If several items are removed from the list, newCount is 0.</p>
				/// <p>If several items are inserted to the list, oldCount is 0.</p>
				/// <p>This event is triggered when the updating is done, original items are not possible to access at the moment.</p>
				/// </remarks>
				Event<ItemChangedProc>			ItemChanged;

				/// <summary>Create an empty list.</summary>
				/// <returns>The created list.</returns>
				static Ptr<IValueObservableList>	Create();

				/// <summary>Create a list with elements copied from another readonly list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueObservableList>	Create(Ptr<IValueReadonlyList> values);

				/// <summary>Create a list with elements copied from another lazy list.</summary>
				/// <returns>The created list.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueObservableList>	Create(collections::LazyList<Value> values);
			};

			/// <summary>
			/// The reflectable version of readonly <see cref="collections::Dictionary`4"/>.
			/// </summary>
			class IValueReadonlyDictionary : public virtual IDescriptable, public Description<IValueReadonlyDictionary>
			{
			public:
				/// <summary>Get all keys.</summary>
				/// <returns>All keys.</returns>
				virtual Ptr<IValueReadonlyList>	GetKeys() = 0;

				/// <summary>Get all values.</summary>
				/// <returns>All values.</returns>
				virtual Ptr<IValueReadonlyList>	GetValues() = 0;

				/// <summary>Get the number of keys.</summary>
				/// <returns>The number of keys. It is also the number of values.</returns>
				virtual vint					GetCount() = 0;

				/// <summary>Get the value associated to a specified key.</summary>
				/// <returns>The reference to the value. It will crash if the key does not exist.</returns>
				/// <param name="key">The key to find.</param>
				virtual Value					Get(const Value& key) = 0;

				/// <summary>Get the underlying collection object, which is boxed to be this interface.</summary>
				/// <returns>The underlying collection object, could be nullptr.</returns>
				virtual const Object*			GetCollectionObject() { return nullptr; }
			};

			/// <summary>
			/// The reflectable version of writable <see cref="collections::Dictionary`4"/>.
			/// </summary>
			/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a dictionary.</remarks>
			/// <example><![CDATA[
			/// // reflectable C++ types
			/// 
			/// namespace mynamespace
			/// {
			///     class MyClass : public Object, public Description<MyClass>
			///     {
			///     public:
			///         MyClass(vint _data = 0)
			///             :data(_data)
			///         {
			///         }
			/// 
			///         vint data;
			///     };
			/// }
			/// 
			/// #define MY_TYPELIST(F)\
			///     F(mynamespace::MyClass)\
			/// 
			/// // it is recommended to put the content below in a separated header file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             MY_TYPELIST(DECL_TYPE_INFO)
			///         }
			///     }
			/// }
			/// 
			/// // it is recommended to put the content below in a separated cpp file
			/// 
			/// namespace vl
			/// {
			///     namespace reflection
			///     {
			///         namespace description
			///         {
			///             using namespace mynamespace;
			/// 
			/// #define _ ,
			/// 
			///             MY_TYPELIST(IMPL_CPP_TYPE_INFO)
			/// 
			///             BEGIN_CLASS_MEMBER(MyClass)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
			///                 CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(vint), { L"data" })
			///                 CLASS_MEMBER_FIELD(data)
			///             END_CLASS_MEMBER(MyClass)
			/// 
			/// #undef  _
			///         }
			///     }
			/// }
			/// 
			/// class MyTypeLoader : public Object, public ITypeLoader
			/// {
			/// public:
			///     void Load(ITypeManager* manager)
			///     {
			///         MY_TYPELIST(ADD_TYPE_INFO)
			///     }
			/// 
			///     void Unload(ITypeManager* manager)
			///     {
			///     }
			/// };
			/// 
			/// // main function
			/// 
			/// int main()
			/// {
			///     LoadPredefinedTypes();
			///     GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
			///     GetGlobalTypeManager()->Load();
			///     {
			///         Dictionary<vint, Ptr<MyClass>> cs;
			///         CopyFrom(cs, Range<vint>(1, 10)
			///             .Select([](vint i) -> Pair<vint, Ptr<MyClass>>
			///             {
			///                 return { i, Ptr(new MyClass(i * i)) };
			///             })
			///         );
			/// 
			///         Value boxed = BoxParameter(cs);
			///         {
			///             auto dictionary = UnboxValue<Ptr<IValueDictionary>>(boxed);
			///             for (vint i = 0; i < dictionary->GetCount(); i++)
			///             {
			///                 Value key = dictionary->GetKeys()->Get(i);
			///                 Console::Write(itow(UnboxValue<Ptr<MyClass>>(dictionary->Get(key))->data) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			/// 
			///         for (vint i = 1; i <= 5; i++)
			///         {
			///             cs.Remove(i * 2);
			///         }
			/// 
			///         {
			///             for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
			///             {
			///                 Value key = boxed.GetProperty(L"Keys").Invoke(L"Get", (Value_xs(), i));
			///                 Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), key)).GetProperty(L"data"))) + L" ");
			///             }
			///             Console::WriteLine(L"");
			///         }
			///     }
			///     DestroyGlobalTypeManager();
			/// }
			/// ]]></example>
			class IValueDictionary : public virtual IValueReadonlyDictionary, public Description<IValueDictionary>
			{
			public:
				/// <summary>Replace the value associated to a specified key.</summary>
				/// <returns>Returns true if the value is replaced.</returns>
				/// <param name="key">The key to find. If the key does not exist, it will be added to the dictionary.</param>
				/// <param name="value">The associated value to replace.</param>
				virtual void					Set(const Value& key, const Value& value) = 0;

				/// <summary>Remove a key with the associated value.</summary>
				/// <returns>Returns true if the key and the value is removed.</returns>
				/// <param name="key">The key to find.</param>
				virtual bool					Remove(const Value& key) = 0;

				/// <summary>Remove all elements.</summary>
				virtual void					Clear() = 0;

				/// <summary>Create an empty dictionary.</summary>
				/// <returns>The created dictionary.</returns>
				static Ptr<IValueDictionary>	Create();

				/// <summary>Create a dictionary with elements copied from another readonly dictionary.</summary>
				/// <returns>The created dictionary.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueDictionary>	Create(Ptr<IValueReadonlyDictionary> values);

				/// <summary>Create a dictionary with elements copied from another lazy list.</summary>
				/// <returns>The created dictionary.</returns>
				/// <param name="values">Elements to copy.</param>
				static Ptr<IValueDictionary>	Create(collections::LazyList<collections::Pair<Value, Value>> values);
			};

/***********************************************************************
Interface Implementation Proxy
***********************************************************************/

			class IValueInterfaceProxy : public virtual IDescriptable, public Description<IValueInterfaceProxy>
			{
			public:
				virtual Value					Invoke(IMethodInfo* methodInfo, Ptr<IValueReadonlyList> arguments) = 0;
			};

			/// <summary>A reflectable version of <see cref="Func`1"/>.</summary>
			/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a function.</remarks>
			class IValueFunctionProxy : public virtual IDescriptable, public Description<IValueFunctionProxy>
			{
			public:
				/// <summary>Call the function.</summary>
				/// <returns>Return value from the function.</returns>
				/// <param name="arguments">Arguments to call the function.</param>
				virtual Value					Invoke(Ptr<IValueReadonlyList> arguments) = 0;
			};

			/// <summary>A reflectable subscription, usually created by the <b>bind</b> expression in Workflow script.</summary>
			class IValueSubscription : public virtual IDescriptable, public Description<IValueSubscription>
			{
				typedef void ValueChangedProc(const Value& newValue);
			public:
				/// <summary>Event that triggered when the binding source is changed.</summary>
				/// <remarks>The first argument is the new value of the binding source.</remarks>
				Event<ValueChangedProc>			ValueChanged;

				/// <summary>Start the subscription.</summary>
				/// <returns>Returns true if this operation succeeded.</summary>
				virtual bool					Open() = 0;

				/// <summary>Manually trigger the event.</summary>
				/// <returns>Returns true if this operation succeeded.</summary>
				virtual bool					Update() = 0;

				/// <summary>Stop the subscription.</summary>
				/// <returns>Returns true if this operation succeeded.</summary>
				virtual bool					Close() = 0;
			};

/***********************************************************************
Interface Implementation Proxy (Implement)
***********************************************************************/

			class ValueInterfaceRoot : public virtual IDescriptable
			{
			protected:
				Ptr<IValueInterfaceProxy>		proxy;

				void SetProxy(Ptr<IValueInterfaceProxy> value)
				{
					proxy = value;
				}
			public:
				Ptr<IValueInterfaceProxy> GetProxy()
				{
					return proxy;
				}
			};

			template<typename T>
			class ValueInterfaceProxy
			{
			};

#pragma warning(push)
#pragma warning(disable:4250)
			template<typename TInterface, typename ...TBaseInterfaces>
			class ValueInterfaceImpl : public virtual ValueInterfaceRoot, public virtual TInterface, public virtual ValueInterfaceProxy<TBaseInterfaces>...
			{
			public:
				~ValueInterfaceImpl()
				{
					FinalizeAggregation();
				}
			};
#pragma warning(pop)

/***********************************************************************
Runtime Exception
***********************************************************************/

			class IValueCallStack : public virtual IDescriptable, public Description<IValueCallStack>
			{
			public:
				virtual Ptr<IValueReadonlyDictionary>	GetLocalVariables() = 0;
				virtual Ptr<IValueReadonlyDictionary>	GetLocalArguments() = 0;
				virtual Ptr<IValueReadonlyDictionary>	GetCapturedVariables() = 0;
				virtual Ptr<IValueReadonlyDictionary>	GetGlobalVariables() = 0;
				virtual WString							GetFunctionName() = 0;
				virtual WString							GetSourceCodeBeforeCodegen() = 0;
				virtual WString							GetSourceCodeAfterCodegen() = 0;
				virtual vint							GetRowBeforeCodegen() = 0;
				virtual vint							GetRowAfterCodegen() = 0;
			};

			class IValueException : public virtual IDescriptable, public Description<IValueException>
			{
			public:
#pragma push_macro("GetMessage")
#if defined GetMessage
#undef GetMessage
#endif
				virtual WString							GetMessage() = 0;
#pragma pop_macro("GetMessage")
				virtual bool							GetFatal() = 0;
				virtual Ptr<IValueReadonlyList>			GetCallStack() = 0;

				static Ptr<IValueException>				Create(const WString& message);
			};
		}
	}
}

#endif


/***********************************************************************
.\METADATA\METADATA.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_METADATA_METADATA
#define VCZH_REFLECTION_METADATA_METADATA


namespace vl
{
	namespace reflection
	{
		namespace description
		{
			template<typename T>
			struct TypeInfoRetriver;

			/// <summary>
			/// A reference holder to an unboxed object.
			/// </summary>
			/// <typeparam name="T">The type of the unboxed object.</typeparam>
			template<typename T>
			struct Unboxed
			{
			private:
				T*				object;
				bool			owned;

			public:
				Unboxed(T* _object, bool _owned) : object(_object), owned(_owned) {}
				Unboxed(Unboxed<T>&& unboxed) : object(unboxed.object), owned(unboxed.owned) { unboxed.object = nullptr; }
				~Unboxed() { if (object && owned) { delete object; } }

				Unboxed() = delete;
				Unboxed(const Unboxed<T>&&) = delete;
				Unboxed<T>& operator=(const Unboxed<T>&) = delete;
				Unboxed<T>& operator=(Unboxed<T>&&) = delete;

				/// <summary>
				/// Get the reference of the unboxed object.
				/// It is recommended only to use this reference when the <see cref="Unboxe`1"/> is still alive.
				/// </summary>
				/// <returns>The unboxed object.</returns>
				T& Ref() const { CHECK_ERROR(object, L"vl::reflection::description::Unboxed<T>::Ref()#The object has been moved away.");  return *object; }

				/// <summary>
				/// Test if the unboxed object is owned.
				/// </summary>
				/// <returns></returns>
				bool IsOwned() const
				{
					return owned;
				}
			};

			template<typename T>
			Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor = nullptr);

			template<typename T>
			T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor = nullptr, const WString& valueName = WString::Unmanaged(L"value"));

			template<typename T>
			Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor = nullptr);

			template<typename T>
			Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor = nullptr, const WString& valueName = WString::Unmanaged(L"value"));

#ifndef VCZH_DEBUG_NO_REFLECTION

/***********************************************************************
TypeInfo
***********************************************************************/

#define DECL_TYPE_INFO(TYPENAME) template<>struct TypeInfo<TYPENAME>{ static const TypeInfoContent content; };
#define IMPL_VL_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::VlppType };
#define IMPL_CPP_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::CppType };
#define IMPL_TYPE_INFO_RENAME(TYPENAME, EXPECTEDNAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #EXPECTEDNAME, L ## #TYPENAME, TypeInfoContent::Renamed };

			struct TypeInfoContent
			{
				enum TypeInfoCppName
				{
					VlppType,			// vl::<type-name>
					CppType,			// <type-name>
					Renamed,			// CppFullTypeName
				};

				const wchar_t*		typeName;
				const wchar_t*		cppFullTypeName;
				TypeInfoCppName		cppName;
			};

			template<typename T>
			struct TypeInfo;

			/// <summary>Get a registered type given a C++ type.</summary>
			/// <returns>Returns the metadata class for this registered type.</returns>
			/// <typeparam name="T">The C++ type to get the registered type.</typeparam>
			/// <remarks>
			/// Returning null means the type registration is declared but the type manager has not started.
			/// Failing to compile means that the type registration is not declared.
			/// See <see cref="Description`1"/> about how to register a type.
			/// </remarks>
			template<typename T>
			ITypeDescriptor* GetTypeDescriptor()
			{
				static vint typeVersion = -1;
				static ITypeDescriptor* cached = nullptr;
				if (auto tm = GetGlobalTypeManager())
				{
					auto currentVersion = tm->GetTypeVersion();
					if (typeVersion != currentVersion)
					{
						cached = GetTypeDescriptor(TypeInfo<T>::content.typeName);
					}
					return cached;
				}
				else
				{
					typeVersion = -1;
					return nullptr;
				}
			}

#endif

#ifndef VCZH_DEBUG_NO_REFLECTION

/***********************************************************************
TypeInfoImp
***********************************************************************/

			class TypeDescriptorTypeInfo : public Object, public ITypeInfo
			{
			protected:
				ITypeDescriptor*						typeDescriptor;
				TypeInfoHint							hint;

			public:
				TypeDescriptorTypeInfo(ITypeDescriptor* _typeDescriptor, TypeInfoHint _hint);
				~TypeDescriptorTypeInfo();

				Decorator								GetDecorator()override;
				TypeInfoHint							GetHint()override;
				ITypeInfo*								GetElementType()override;
				ITypeDescriptor*						GetTypeDescriptor()override;
				vint									GetGenericArgumentCount()override;
				ITypeInfo*								GetGenericArgument(vint index)override;
				WString									GetTypeFriendlyName()override;
			};

			class DecoratedTypeInfo : public Object, public ITypeInfo
			{
			protected:
				Ptr<ITypeInfo>							elementType;

			public:
				DecoratedTypeInfo(Ptr<ITypeInfo> _elementType);
				~DecoratedTypeInfo();

				TypeInfoHint							GetHint()override;
				ITypeInfo*								GetElementType()override;
				ITypeDescriptor*						GetTypeDescriptor()override;
				vint									GetGenericArgumentCount()override;
				ITypeInfo*								GetGenericArgument(vint index)override;
			};

			class RawPtrTypeInfo : public DecoratedTypeInfo
			{
			public:
				RawPtrTypeInfo(Ptr<ITypeInfo> _elementType);
				~RawPtrTypeInfo();

				Decorator								GetDecorator()override;
				WString									GetTypeFriendlyName()override;
			};

			class SharedPtrTypeInfo : public DecoratedTypeInfo
			{
			public:
				SharedPtrTypeInfo(Ptr<ITypeInfo> _elementType);
				~SharedPtrTypeInfo();

				Decorator								GetDecorator()override;
				WString									GetTypeFriendlyName()override;
			};

			class NullableTypeInfo : public DecoratedTypeInfo
			{
			public:
				NullableTypeInfo(Ptr<ITypeInfo> _elementType);
				~NullableTypeInfo();

				Decorator								GetDecorator()override;
				WString									GetTypeFriendlyName()override;
			};

			class GenericTypeInfo : public DecoratedTypeInfo
			{
			protected:
				collections::List<Ptr<ITypeInfo>>		genericArguments;

			public:
				GenericTypeInfo(Ptr<ITypeInfo> _elementType);
				~GenericTypeInfo();

				Decorator								GetDecorator()override;
				vint									GetGenericArgumentCount()override;
				ITypeInfo*								GetGenericArgument(vint index)override;
				WString									GetTypeFriendlyName()override;

				void									AddGenericArgument(Ptr<ITypeInfo> value);
			};

			class AttributeInfoImpl : public Object, public IAttributeInfo
			{
				using TypeValuePair = collections::Pair<ITypeDescriptor*, Value>;
			protected:
				ITypeDescriptor*						attributeType = nullptr;
				collections::List<TypeValuePair>		values;
			public:
				AttributeInfoImpl(ITypeDescriptor* _attributeType);

				ITypeDescriptor*						GetAttributeType()override;
				vint									GetAttributeValueCount()override;
				ITypeDescriptor*						GetAttributeValueType(vint index)override;
				Value									GetAttributeValue(vint index)override;
				void									AddValue(ITypeDescriptor* valueType, const Value& value);
			};

#endif

#ifndef VCZH_DEBUG_NO_REFLECTION

/***********************************************************************
MemberInfoBase
***********************************************************************/

			template<typename TMemberInfo>
			class MemberInfoBase;

			class AttributeBagSource : public Object
			{
				template<typename TMemberInfo>
				friend class MemberInfoBase;
			protected:
				collections::Group<IMemberInfo*, Ptr<IAttributeInfo>>		attributes;
				IMemberInfo*												lastRegisteredMember = nullptr;

				virtual vint GetAttributeCountInternal(IMemberInfo* memberInfo)
				{
					if (!attributes.Contains(memberInfo))
					{
						return 0;
					}
					return attributes.Get(memberInfo).Count();
				}

				virtual IAttributeInfo* GetAttributeInternal(IMemberInfo* memberInfo, vint index)
				{
					if (!attributes.Contains(memberInfo))
					{
						return nullptr;
					}
					auto&& infos = attributes.Get(memberInfo);
					return 0 <= index && index < infos.Count() ? infos[index].Obj() : nullptr;
				}
			public:
				void									RegisterAttribute(IMemberInfo* memberInfo, Ptr<IAttributeInfo> info);
				IMemberInfo*							GetLastRegisteredMember()const;
				void									SetLastRegisteredMember(IMemberInfo* member);
			};

			template<typename TMemberInfo>
			class MemberInfoBase : public Object, public TMemberInfo
			{
			protected:

				AttributeBagSource* GetAttributeBagSource()
				{
#define ERROR_MESSAGE_PREFIX L"vl::reflection::description::MemberInfoBase<TMemberInfo>::GetAttributeBagSource()#"
					auto owner = this->GetOwnerTypeDescriptor();
					CHECK_ERROR(owner, ERROR_MESSAGE_PREFIX L"GetOwnerTypeDescriptor() should not return nullptr.");
					auto source = dynamic_cast<AttributeBagSource*>(owner);
					CHECK_ERROR(source, ERROR_MESSAGE_PREFIX L"GetOwnerTypeDescriptor() should be an AttributeBagSource instance.");
					return source;
#undef ERROR_MESSAGE_PREFIX
				}

			public:
				vint GetAttributeCount()
				{
					return GetAttributeBagSource()->GetAttributeCountInternal(this);
				}

				IAttributeInfo* GetAttribute(vint index)
				{
					return GetAttributeBagSource()->GetAttributeInternal(this, index);
				}
			};

/***********************************************************************
SerializableTypeDescriptor
***********************************************************************/

			class TypeDescriptorImplBase : public AttributeBagSource, public ITypeDescriptor, private ITypeDescriptor::ICpp
			{
			private:
				TypeDescriptorFlags							typeDescriptorFlags;
				const TypeInfoContent*						typeInfoContent;
				WString										typeName;
				WString										cppFullTypeName;

				const WString&								GetFullName()override;

			protected:
				const TypeInfoContent*						GetTypeInfoContentInternal();
				virtual void								LoadForAttributeAccess();

			public:
				TypeDescriptorImplBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
				~TypeDescriptorImplBase();

				vint										GetAttributeCount()override;
				IAttributeInfo*								GetAttribute(vint index)override;
				ITypeDescriptor::ICpp*						GetCpp()override;
				TypeDescriptorFlags							GetTypeDescriptorFlags()override;
				const WString&								GetTypeName()override;
			};

			class ValueTypeDescriptorBase : public TypeDescriptorImplBase
			{
			protected:
				bool										loaded;
				Ptr<IValueType>								valueType;
				Ptr<IEnumType>								enumType;
				Ptr<ISerializableType>						serializableType;

				virtual void								LoadInternal();;
				void										Load();
				void										LoadForAttributeAccess()override;
			public:
				ValueTypeDescriptorBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
				~ValueTypeDescriptorBase();

				bool										IsAggregatable()override;
				IValueType*									GetValueType()override;
				IEnumType*									GetEnumType()override;
				ISerializableType*							GetSerializableType()override;

				vint										GetBaseTypeDescriptorCount()override;
				ITypeDescriptor*							GetBaseTypeDescriptor(vint index)override;
				bool										CanConvertTo(ITypeDescriptor* targetType)override;
				vint										GetPropertyCount()override;
				IPropertyInfo*								GetProperty(vint index)override;
				bool										IsPropertyExists(const WString& name, bool inheritable)override;
				IPropertyInfo*								GetPropertyByName(const WString& name, bool inheritable)override;
				vint										GetEventCount()override;
				IEventInfo*									GetEvent(vint index)override;
				bool										IsEventExists(const WString& name, bool inheritable)override;
				IEventInfo*									GetEventByName(const WString& name, bool inheritable)override;
				vint										GetMethodGroupCount()override;
				IMethodGroupInfo*							GetMethodGroup(vint index)override;
				bool										IsMethodGroupExists(const WString& name, bool inheritable)override;
				IMethodGroupInfo*							GetMethodGroupByName(const WString& name, bool inheritable)override;
				IMethodGroupInfo*							GetConstructorGroup()override;
			};

			template<typename T, TypeDescriptorFlags TDFlags>
			class TypedValueTypeDescriptorBase : public ValueTypeDescriptorBase
			{
			public:
				TypedValueTypeDescriptorBase()
					:ValueTypeDescriptorBase(TDFlags, &TypeInfo<T>::content)
				{
				}
			};

/***********************************************************************
ParameterInfoImpl
***********************************************************************/

			class ParameterInfoImpl : public MemberInfoBase<IParameterInfo>
			{
			protected:
				IMethodInfo*							ownerMethod;
				WString									name;
				Ptr<ITypeInfo>							type;
			public:
				ParameterInfoImpl(IMethodInfo* _ownerMethod, const WString& _name, Ptr<ITypeInfo> _type);
				~ParameterInfoImpl();

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				const WString&							GetName()override;
				ITypeInfo*								GetType()override;
				IMethodInfo*							GetOwnerMethod()override;
			};

/***********************************************************************
MethodInfoImpl
***********************************************************************/

			class MethodInfoImpl : public MemberInfoBase<IMethodInfo>
			{
				friend class PropertyInfoImpl;
			protected:
				IMethodGroupInfo*						ownerMethodGroup;
				IPropertyInfo*							ownerProperty;
				collections::List<Ptr<IParameterInfo>>	parameters;
				Ptr<ITypeInfo>							returnInfo;
				bool									isStatic;

				virtual Value							InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)=0;
				virtual Value							CreateFunctionProxyInternal(const Value& thisObject) = 0;
			public:
				MethodInfoImpl(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic);
				~MethodInfoImpl();

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				IPropertyInfo*							GetOwnerProperty()override;
				const WString&							GetName()override;
				IMethodGroupInfo*						GetOwnerMethodGroup()override;
				vint									GetParameterCount()override;
				IParameterInfo*							GetParameter(vint index)override;
				ITypeInfo*								GetReturn()override;
				bool									IsStatic()override;
				void									CheckArguments(collections::Array<Value>& arguments)override;
				Value									Invoke(const Value& thisObject, collections::Array<Value>& arguments)override;
				Value									CreateFunctionProxy(const Value& thisObject)override;
				bool									AddParameter(Ptr<IParameterInfo> parameter);
				bool									SetOwnerMethodgroup(IMethodGroupInfo* _ownerMethodGroup);
			};

/***********************************************************************
MethodGroupInfoImpl
***********************************************************************/

			class MethodGroupInfoImpl : public Object, public IMethodGroupInfo
			{
			protected:
				ITypeDescriptor*						ownerTypeDescriptor;
				WString									name;
				collections::List<Ptr<IMethodInfo>>		methods;
			public:
				MethodGroupInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name);
				~MethodGroupInfoImpl();

				vint									GetAttributeCount()override;
				IAttributeInfo*							GetAttribute(vint index)override;

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				const WString&							GetName()override;
				vint									GetMethodCount()override;
				IMethodInfo*							GetMethod(vint index)override;
				bool									AddMethod(Ptr<IMethodInfo> _method);
			};

/***********************************************************************
EventInfoImpl
***********************************************************************/

			class EventInfoImpl : public MemberInfoBase<IEventInfo>
			{
				friend class PropertyInfoImpl;

			protected:
				ITypeDescriptor*						ownerTypeDescriptor;
				collections::List<IPropertyInfo*>		observingProperties;
				WString									name;
				Ptr<ITypeInfo>							handlerType;

				virtual Ptr<IEventHandler>				AttachInternal(DescriptableObject* thisObject, Ptr<IValueFunctionProxy> handler)=0;
				virtual bool							DetachInternal(DescriptableObject* thisObject, Ptr<IEventHandler> handler)=0;
				virtual void							InvokeInternal(DescriptableObject* thisObject, Ptr<IValueReadonlyList> arguments)=0;
				virtual Ptr<ITypeInfo>					GetHandlerTypeInternal()=0;
			public:
				EventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name);
				~EventInfoImpl();

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				const WString&							GetName()override;
				ITypeInfo*								GetHandlerType()override;
				vint									GetObservingPropertyCount()override;
				IPropertyInfo*							GetObservingProperty(vint index)override;
				Ptr<IEventHandler>						Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)override;
				bool									Detach(const Value& thisObject, Ptr<IEventHandler> handler)override;
				void									Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments)override;
			};

/***********************************************************************
TypeDescriptorImpl
***********************************************************************/

			class PropertyInfoImpl : public MemberInfoBase<IPropertyInfo>
			{
			protected:
				ITypeDescriptor*						ownerTypeDescriptor;
				WString									name;
				Ptr<ICpp>								cpp;
				MethodInfoImpl*							getter;
				MethodInfoImpl*							setter;
				EventInfoImpl*							valueChangedEvent;

			public:
				PropertyInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent);
				~PropertyInfoImpl();

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				const WString&							GetName()override;
				IPropertyInfo::ICpp*					GetCpp()override;

				bool									IsReadable()override;
				bool									IsWritable()override;
				ITypeInfo*								GetReturn()override;
				IMethodInfo*							GetGetter()override;
				IMethodInfo*							GetSetter()override;
				IEventInfo*								GetValueChangedEvent()override;
				Value									GetValue(const Value& thisObject)override;
				void									SetValue(Value& thisObject, const Value& newValue)override;
			};

			class PropertyInfoImpl_StaticCpp : public PropertyInfoImpl, private IPropertyInfo::ICpp
			{
			private:
				WString									referenceTemplate;

				const WString&							GetReferenceTemplate()override;

			public:
				PropertyInfoImpl_StaticCpp(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, MethodInfoImpl* _getter, MethodInfoImpl* _setter, EventInfoImpl* _valueChangedEvent, const WString& _referenceTemplate);
				~PropertyInfoImpl_StaticCpp();

				IPropertyInfo::ICpp*					GetCpp()override;
			};

/***********************************************************************
FieldInfoImpl
***********************************************************************/

			class FieldInfoImpl : public MemberInfoBase<IPropertyInfo>
			{
			protected:
				ITypeDescriptor*						ownerTypeDescriptor;
				Ptr<ITypeInfo>							returnInfo;
				WString									name;

				virtual Value							GetValueInternal(const Value& thisObject)=0;
				virtual void							SetValueInternal(Value& thisObject, const Value& newValue)=0;
			public:
				FieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Ptr<ITypeInfo> _returnInfo);
				~FieldInfoImpl();

				ITypeDescriptor*						GetOwnerTypeDescriptor()override;
				const WString&							GetName()override;
				bool									IsReadable()override;
				bool									IsWritable()override;
				ITypeInfo*								GetReturn()override;
				IMethodInfo*							GetGetter()override;
				IMethodInfo*							GetSetter()override;
				IEventInfo*								GetValueChangedEvent()override;
				Value									GetValue(const Value& thisObject)override;
				void									SetValue(Value& thisObject, const Value& newValue)override;
			};

/***********************************************************************
TypeDescriptorImpl
***********************************************************************/

			class TypeDescriptorImpl : public TypeDescriptorImplBase
			{
			private:
				bool														loaded;
				collections::List<ITypeDescriptor*>							baseTypeDescriptors;
				collections::Dictionary<WString, Ptr<IPropertyInfo>>		properties;
				collections::Dictionary<WString, Ptr<IEventInfo>>			events;
				collections::Dictionary<WString, Ptr<MethodGroupInfoImpl>>	methodGroups;
				Ptr<MethodGroupInfoImpl>									constructorGroup;

			protected:
				MethodGroupInfoImpl*		PrepareMethodGroup(const WString& name);
				MethodGroupInfoImpl*		PrepareConstructorGroup();
				IPropertyInfo*				AddProperty(Ptr<IPropertyInfo> value);
				IEventInfo*					AddEvent(Ptr<IEventInfo> value);
				IMethodInfo*				AddMethod(const WString& name, Ptr<MethodInfoImpl> value);
				IMethodInfo*				AddConstructor(Ptr<MethodInfoImpl> value);
				void						AddBaseType(ITypeDescriptor* value);

				virtual void				LoadInternal()=0;
				void						Load();
				void						LoadForAttributeAccess()override;
			public:
				TypeDescriptorImpl(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
				~TypeDescriptorImpl();

				bool						IsAggregatable()override;
				IValueType*					GetValueType()override;
				IEnumType*					GetEnumType()override;
				ISerializableType*			GetSerializableType()override;

				vint						GetBaseTypeDescriptorCount()override;
				ITypeDescriptor*			GetBaseTypeDescriptor(vint index)override;
				bool						CanConvertTo(ITypeDescriptor* targetType)override;

				vint						GetPropertyCount()override;
				IPropertyInfo*				GetProperty(vint index)override;
				bool						IsPropertyExists(const WString& name, bool inheritable)override;
				IPropertyInfo*				GetPropertyByName(const WString& name, bool inheritable)override;

				vint						GetEventCount()override;
				IEventInfo*					GetEvent(vint index)override;
				bool						IsEventExists(const WString& name, bool inheritable)override;
				IEventInfo*					GetEventByName(const WString& name, bool inheritable)override;

				vint						GetMethodGroupCount()override;
				IMethodGroupInfo*			GetMethodGroup(vint index)override;
				bool						IsMethodGroupExists(const WString& name, bool inheritable)override;
				IMethodGroupInfo*			GetMethodGroupByName(const WString& name, bool inheritable)override;
				IMethodGroupInfo*			GetConstructorGroup()override;
			};

#endif

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

/***********************************************************************
CustomFieldInfoImpl
***********************************************************************/

			template<typename TClass, typename TField>
			class CustomFieldInfoImpl : public FieldInfoImpl
			{
			protected:
				TField TClass::*				fieldRef;

				Value GetValueInternal(const Value& thisObject)override
				{
					TClass* object = UnboxValue<TClass*>(thisObject);
					if (object)
					{
						return BoxParameter(object->*fieldRef, GetReturn()->GetTypeDescriptor());
					}
					return Value();
				}

				void SetValueInternal(Value& thisObject, const Value& newValue)override
				{
					if constexpr (std::is_copy_assignable_v<TField>)
					{
						TClass* object = UnboxValue<TClass*>(thisObject);
						if (object)
						{
							auto result = UnboxParameter<TField>(newValue, GetReturn()->GetTypeDescriptor(), L"newValue");
							object->*fieldRef = result.Ref();
						}
					}
					else
					{
						throw PropertyIsNotWritableException(this);
					}
				}
			public:
				CustomFieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, TField TClass::* _fieldRef)
					:FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
					, fieldRef(_fieldRef)
				{
				}

				IPropertyInfo::ICpp* GetCpp()override
				{
					return nullptr;
				}

				bool IsWritable()override
				{
					return std::is_copy_assignable_v<TField>;
				}
			};

#endif

/***********************************************************************
PrimitiveTypeDescriptor
***********************************************************************/

#ifndef VCZH_DEBUG_NO_REFLECTION

			template<typename T>
			class SerializableValueType : public Object, public virtual IValueType
			{
			public:
				Value CreateDefault()override
				{
					return BoxValue<T>(TypedValueSerializerProvider<T>::GetDefaultValue());
				}
			};

			template<typename T>
			class SerializableType : public Object, public virtual ISerializableType
			{
			public:
				bool Serialize(const Value& input, WString& output)override
				{
					return TypedValueSerializerProvider<T>::Serialize(UnboxValue<T>(input), output);
				}

				bool Deserialize(const WString& input, Value& output)override
				{
					T value;
					if (!TypedValueSerializerProvider<T>::Deserialize(input, value))
					{
						return false;
					}
					output = BoxValue<T>(value);
					return true;
				}
			};

#endif

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

			template<typename T>
			class PrimitiveTypeDescriptor : public TypedValueTypeDescriptorBase<T, TypeDescriptorFlags::Primitive>
			{
			protected:
				void LoadInternal()override
				{
					this->valueType = Ptr(new SerializableValueType<T>());
					this->serializableType = Ptr(new SerializableType<T>());
				}
			};

/***********************************************************************
EnumTypeDescriptor
***********************************************************************/

			template<typename T>
			class EnumValueType : public Object, public virtual IValueType
			{
			public:
				Value CreateDefault()override
				{
					return BoxValue<T>(static_cast<T>(0));
				}
			};

			template<typename T, bool Flag>
			class EnumType : public Object, public virtual IEnumType
			{
			protected:
				collections::Dictionary<WString, T>			candidates;

			public:
				void AddItem(WString name, T value)
				{
					candidates.Add(name, value);
				}

				bool IsFlagEnum()override
				{
					return Flag;
				}

				vint GetItemCount()override
				{
					return candidates.Count();
				}

				WString GetItemName(vint index)override
				{
					if (index < 0 || index >= candidates.Count())
					{
						return L"";
					}
					return candidates.Keys()[index];
				}

				vuint64_t GetItemValue(vint index)override
				{
					if (index < 0 || index >= candidates.Count())
					{
						return 0;
					}
					return static_cast<vuint64_t>(candidates.Values()[index]);
				}

				vint IndexOfItem(WString name)override
				{
					return candidates.Keys().IndexOf(name);
				}

				Value ToEnum(vuint64_t value)override
				{
					return BoxValue<T>(static_cast<T>(value));
				}

				vuint64_t FromEnum(const Value& value)override
				{
					return static_cast<vuint64_t>(UnboxValue<T>(value));
				}
			};

			template<typename T, TypeDescriptorFlags TDFlags>
			class EnumTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
			{
				using TEnumType = EnumType<T, TDFlags == TypeDescriptorFlags::FlagEnum>;
			protected:
				Ptr<TEnumType>					enumType;

				void LoadInternal()override
				{
					this->enumType = Ptr(new TEnumType);
					this->valueType = Ptr(new EnumValueType<T>());
					TypedValueTypeDescriptorBase<T, TDFlags>::enumType = enumType;
				}
			};

/***********************************************************************
StructTypeDescriptor
***********************************************************************/

			template<typename T>
			class StructValueType : public Object, public virtual IValueType
			{
			public:
				Value CreateDefault()override
				{
					return BoxValue<T>(T{});
				}
			};

			template<typename T, TypeDescriptorFlags TDFlags>
			class StructTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
			{
			protected:
				template<typename TField>
				class StructFieldInfo : public FieldInfoImpl
				{
				protected:
					TField T::*					field;

					Value GetValueInternal(const Value& thisObject)override
					{
						auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
						if (!structValue)
						{
							throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
						}
						return BoxValue<TField>(structValue->value.*field);
					}

					void SetValueInternal(Value& thisObject, const Value& newValue)override
					{
						auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
						if (!structValue)
						{
							throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
						}
						(structValue->value.*field) = UnboxValue<TField>(newValue);
					}
				public:
					StructFieldInfo(ITypeDescriptor* _ownerTypeDescriptor, TField T::* _field, const WString& _name)
						:field(_field)
						, FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
					{
					}

					IPropertyInfo::ICpp* GetCpp()override
					{
						return nullptr;
					}
				};

			protected:
				collections::Dictionary<WString, Ptr<IPropertyInfo>>		fields;

			public:
				IPropertyInfo* AddField(Ptr<IPropertyInfo> value)
				{
					fields.Add(value->GetName(), value);
					this->SetLastRegisteredMember(value.Obj());
					return value.Obj();
				}

				StructTypeDescriptor()
				{
					this->valueType = Ptr(new StructValueType<T>());
				}

				vint GetPropertyCount()override
				{
					this->Load();
					return fields.Count();
				}

				IPropertyInfo* GetProperty(vint index)override
				{
					this->Load();
					if (index < 0 || index >= fields.Count())
					{
						return nullptr;
					}
					return fields.Values()[index].Obj();
				}

				bool IsPropertyExists(const WString& name, bool inheritable)override
				{
					this->Load();
					return fields.Keys().Contains(name);
				}

				IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override
				{
					this->Load();
					vint index = fields.Keys().IndexOf(name);
					if (index == -1) return nullptr;
					return fields.Values()[index].Obj();
				}
			};
#endif
		}
	}
}

#endif


/***********************************************************************
.\BOXING\TYPEINFORETRIVER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_TYPEINFORETRIVER
#define VCZH_REFLECTION_BOXING_TYPEINFORETRIVER


namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
TypeFlagTester
***********************************************************************/

			enum class TypeFlags
			{
				NonGenericType			=0,
				FunctionType			=1<<0,
				EnumerableType			=1<<1,
				ReadonlyListType		=1<<2,
				ArrayType				=1<<3,
				ListType				=1<<4,
				ObservableListType		=1<<5,
				ReadonlyDictionaryType	=1<<6,
				DictionaryType			=1<<7,
			};

			template<typename T>
			struct ValueRetriver
			{
				T* pointer;
			};

			template<typename T>
			struct ValueRetriver<T&>
			{
				T* pointer;
			};

			template<typename TDerived, TypeFlags Flag>
			struct TypeFlagTester
			{
				static const TypeFlags									Result=TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::FunctionType>
			{
				template<typename T>
				static void* Inherit(const Func<T>* source){ return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::FunctionType:TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::EnumerableType>
			{
				template<typename T>
				static void* Inherit(const collections::LazyList<T>* source){ return {}; }
				template<typename T>
				static void* Inherit(const collections::IEnumerable<T>* source) { return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::EnumerableType:TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::ReadonlyListType>
			{
				template<typename T>
				static void* Inherit(const collections::Array<T>* source){ return {}; }
				template<typename T>
				static void* Inherit(const collections::List<T>* source) { return {}; }
				template<typename T>
				static void* Inherit(const collections::SortedList<T>* source) { return {}; }
				template<typename T>
				static void* Inherit(const collections::ObservableListBase<T>* source) { return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyListType:TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::ArrayType>
			{
				template<typename T>
				static void* Inherit(collections::Array<T>* source) { return {}; }
				static char Inherit(void* source) { return {}; }
				static char Inherit(const void* source) { return {}; }

				static const TypeFlags									Result = sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer)) == sizeof(void*) ? TypeFlags::ArrayType : TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::ListType>
			{
				template<typename T>
				static void* Inherit(collections::List<T>* source) { return {}; }
				template<typename T>
				static void* Inherit(collections::ObservableListBase<T>* source) { return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ListType:TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::ObservableListType>
			{
				template<typename T>
				static void* Inherit(collections::ObservableList<T>* source) { return {}; }
				static char Inherit(void* source) { return {}; }
				static char Inherit(const void* source) { return {}; }

				static const TypeFlags									Result = sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer)) == sizeof(void*) ? TypeFlags::ObservableListType : TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::ReadonlyDictionaryType>
			{
				template<typename K, typename V>
				static void* Inherit(const collections::Dictionary<K, V>* source){ return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyDictionaryType:TypeFlags::NonGenericType;
			};

			template<typename TDerived>
			struct TypeFlagTester<TDerived, TypeFlags::DictionaryType>
			{
				template<typename K, typename V>
				static void* Inherit(collections::Dictionary<K, V>* source){ return {}; }
				static char Inherit(void* source){ return {}; }
				static char Inherit(const void* source){ return {}; }

				static const TypeFlags									Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::DictionaryType:TypeFlags::NonGenericType;
			};

/***********************************************************************
TypeFlagSelector
***********************************************************************/

			template<typename T, TypeFlags Flag>
			struct TypeFlagSelectorCase
			{
				static const  TypeFlags									Result=TypeFlags::NonGenericType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::FunctionType)>
			{
				static const  TypeFlags									Result=TypeFlags::FunctionType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType)>
			{
				static const  TypeFlags									Result=TypeFlags::EnumerableType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType)>
			{
				static const  TypeFlags									Result = TypeFlags::ReadonlyListType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ArrayType)>
			{
				static const  TypeFlags									Result = TypeFlags::ArrayType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ListType)>
			{
				static const  TypeFlags									Result = TypeFlags::ListType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ListType|(vint)TypeFlags::ObservableListType)>
			{
				static const  TypeFlags									Result = TypeFlags::ObservableListType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyDictionaryType)>
			{
				static const  TypeFlags									Result=TypeFlags::ReadonlyDictionaryType;
			};

			template<typename T>
			struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType |(vint)TypeFlags::ReadonlyDictionaryType |(vint)TypeFlags::DictionaryType)>
			{
				static const  TypeFlags									Result=TypeFlags::DictionaryType;
			};

			template<typename T>
			struct TypeFlagSelector
			{
				static const TypeFlags									Result =
					TypeFlagSelectorCase<
					T, 
					(TypeFlags)
					( (vint)TypeFlagTester<T, TypeFlags::FunctionType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::EnumerableType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::ReadonlyListType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::ArrayType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::ListType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::ObservableListType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::ReadonlyDictionaryType>::Result
					| (vint)TypeFlagTester<T, TypeFlags::DictionaryType>::Result
					)
					>::Result;
			};

/***********************************************************************
TypeHintTester
***********************************************************************/

			template<typename T>
			struct TypeHintTester
			{
				static const TypeInfoHint								Result = TypeInfoHint::Normal;
			};

			template<TypeFlags Flags>
			struct TypeHintTesterForReference
			{
				static const TypeInfoHint								Result = TypeInfoHint::NativeCollectionReference;
			};

			template<>
			struct TypeHintTesterForReference<TypeFlags::NonGenericType>
			{
				static const TypeInfoHint								Result = TypeInfoHint::Normal;
			};

			template<>
			struct TypeHintTesterForReference<TypeFlags::FunctionType>
			{
				static const TypeInfoHint								Result = TypeInfoHint::Normal;
			};

			template<typename T>
			struct TypeHintTester<T*>
			{
				static const TypeInfoHint								Result = TypeHintTester<T>::Result;
			};

			template<typename T>
			struct TypeHintTester<T&>
			{
				static const TypeInfoHint								Result = TypeHintTester<T>::Result == TypeInfoHint::Normal
																					? TypeHintTesterForReference<TypeFlagSelector<T&>::Result>::Result
																					: TypeHintTester<T>::Result
																					;
			};

			template<typename T>
			struct TypeHintTester<const T>
			{
				static const TypeInfoHint								Result = TypeHintTester<T>::Result;
			};

			template<typename T>
			struct TypeHintTester<collections::LazyList<T>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::LazyList;
			};

			template<typename T>
			struct TypeHintTester<collections::Array<T>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::Array;
			};

			template<typename T>
			struct TypeHintTester<collections::List<T>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::List;
			};

			template<typename T>
			struct TypeHintTester<collections::SortedList<T>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::SortedList;
			};

			template<typename T>
			struct TypeHintTester<collections::ObservableList<T>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::ObservableList;
			};

			template<typename K, typename V>
			struct TypeHintTester<collections::Dictionary<K, V>>
			{
				static const TypeInfoHint								Result = TypeInfoHint::Dictionary;
			};

/***********************************************************************
DetailTypeInfoRetriver
***********************************************************************/

			template<typename T, TypeFlags Flag>
			struct DetailTypeInfoRetriver;

/***********************************************************************
Basic Types
***********************************************************************/

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>
			{
				static const ITypeInfo::Decorator						Decorator=ITypeInfo::TypeDescriptor;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					return Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<T>(), hint));
				}
#endif
			};

/***********************************************************************
Decorated Types
***********************************************************************/

			template<typename T>
			struct DetailTypeInfoRetriver<T*, TypeFlags::NonGenericType>
			{
				typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>	UpLevelRetriver;

				static const ITypeInfo::Decorator								Decorator=ITypeInfo::RawPtr;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					return Ptr(new RawPtrTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
				}
#endif
			};

			template<typename T>
			struct DetailTypeInfoRetriver<Ptr<T>, TypeFlags::NonGenericType>
			{
				typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>	UpLevelRetriver;

				static const ITypeInfo::Decorator								Decorator=ITypeInfo::SharedPtr;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					return Ptr(new SharedPtrTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
				}
#endif
			};

			template<typename T>
			struct DetailTypeInfoRetriver<Nullable<T>, TypeFlags::NonGenericType>
			{
				typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>	UpLevelRetriver;

				static const ITypeInfo::Decorator								Decorator=ITypeInfo::Nullable;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					return Ptr(new NullableTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
				}
#endif
			};

/***********************************************************************
Containers
***********************************************************************/

			template<typename T, typename TCollectionType>
			struct DetailTypeInfoRetriver_Template1
			{
				typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>	UpLevelRetriver;

				static const ITypeInfo::Decorator								Decorator = UpLevelRetriver::Decorator;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					auto arrayType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<TCollectionType>(), hint));

					auto genericType = Ptr(new GenericTypeInfo(arrayType));
					genericType->AddGenericArgument(TypeInfoRetriver<typename T::ElementType>::CreateTypeInfo());

					auto type = Ptr(new SharedPtrTypeInfo(genericType));
					return type;
				}
#endif
			};

			template<typename T, typename TCollectionType>
			struct DetailTypeInfoRetriver_Template2
			{
				typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>	UpLevelRetriver;

				static const ITypeInfo::Decorator								Decorator = UpLevelRetriver::Decorator;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					auto arrayType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<TCollectionType>(), hint));

					auto genericType = Ptr(new GenericTypeInfo(arrayType));
					genericType->AddGenericArgument(TypeInfoRetriver<typename T::KeyContainer::ElementType>::CreateTypeInfo());
					genericType->AddGenericArgument(TypeInfoRetriver<typename T::ValueContainer::ElementType>::CreateTypeInfo());

					auto type = Ptr(new SharedPtrTypeInfo(genericType));
					return type;
				}
#endif
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::EnumerableType> : DetailTypeInfoRetriver_Template1<T, IValueEnumerable>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyListType> : DetailTypeInfoRetriver_Template1<T, IValueReadonlyList>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::ArrayType> : DetailTypeInfoRetriver_Template1<T, IValueArray>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::ListType> : DetailTypeInfoRetriver_Template1<T, IValueList>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::ObservableListType> : DetailTypeInfoRetriver_Template1<T, IValueObservableList>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyDictionaryType> : DetailTypeInfoRetriver_Template2<T, IValueReadonlyDictionary>
			{
			};

			template<typename T>
			struct DetailTypeInfoRetriver<T, TypeFlags::DictionaryType> : DetailTypeInfoRetriver_Template2<T, IValueDictionary>
			{
			};

/***********************************************************************
Functions
***********************************************************************/

#ifndef VCZH_DEBUG_NO_REFLECTION
			namespace internal_helper
			{
				template<typename T>
				struct GenericArgumentAdder
				{
					static void Add(Ptr<GenericTypeInfo> genericType)
					{
					}
				};

				template<typename T0, typename ...TNextArgs>
				struct GenericArgumentAdder<TypeTuple<T0, TNextArgs...>>
				{
					static void Add(Ptr<GenericTypeInfo> genericType)
					{
						genericType->AddGenericArgument(TypeInfoRetriver<T0>::CreateTypeInfo());
						GenericArgumentAdder<TypeTuple<TNextArgs...>>::Add(genericType);
					}
				};
			}
#endif

			template<typename R, typename ...TArgs>
			struct DetailTypeInfoRetriver<Func<R(TArgs...)>, TypeFlags::FunctionType>
			{
				typedef DetailTypeInfoRetriver<const Func<R(TArgs...)>, TypeFlags::NonGenericType>	UpLevelRetriver;
 
				static const ITypeInfo::Decorator								Decorator=UpLevelRetriver::Decorator;
 
#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
				{
					auto functionType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<IValueFunctionProxy>(), hint));
 
					auto genericType = Ptr(new GenericTypeInfo(functionType));
					genericType->AddGenericArgument(TypeInfoRetriver<R>::CreateTypeInfo());
					internal_helper::GenericArgumentAdder<TypeTuple<TArgs...>>::Add(genericType);

					auto type = Ptr(new SharedPtrTypeInfo(genericType));
					return type;
				}
#endif
			};

/***********************************************************************
TypeInfoRetriver
***********************************************************************/

			template<typename T>
			struct TypeInfoRetriver
			{
				static const TypeFlags												TypeFlag = TypeFlagSelector<T>::Result;
				static const TypeInfoHint											Hint = TypeHintTester<T>::Result;
				typedef DetailTypeInfoRetriver<std::remove_cvref_t<T>, TypeFlag>	Detail;
				static const ITypeInfo::Decorator									Decorator = Detail::Decorator;

#ifndef VCZH_DEBUG_NO_REFLECTION
				static Ptr<ITypeInfo> CreateTypeInfo()
				{
					return DetailTypeInfoRetriver<std::remove_cvref_t<T>, TypeFlag>::CreateTypeInfo(Hint);
				}
#endif
			};

			template<>
			struct TypeInfoRetriver<void> : public TypeInfoRetriver<VoidValue>
			{
			};
		}
	}
}

#endif


/***********************************************************************
.\BOXING\BOXINGVALUE.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_BOXINGVALUE
#define VCZH_REFLECTION_BOXING_BOXINGVALUE


namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
BoxValue, UnboxValue
***********************************************************************/

			template<typename T, ITypeInfo::Decorator Decorator>
			struct ValueAccessor
			{
			};

			/// <summary>Box an reflectable object. Its type cannot be generic.</summary>
			/// <returns>The boxed value.</returns>
			/// <typeparam name="T">Type of the object.</typeparam>
			/// <param name="object">The object to box.</param>
			/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
			template<typename T>
			Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor)
			{
				using Type = std::remove_cvref_t<T>;
				return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::BoxValue(object, typeDescriptor);
			}
			
			/// <summary>Unbox a reflectable object. Its type cannot be generic.</summary>
			/// <returns>The unboxed object.</returns>
			/// <typeparam name="T">Type of the object.</typeparam>
			/// <param name="value">The value to unbox.</param>
			/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
			/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
			template<typename T>
			T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
			{
				using Type = std::remove_cvref_t<T>;
				return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::UnboxValue(value, typeDescriptor, valueName);
			}

/***********************************************************************
Basic Types
***********************************************************************/

			template<typename T>
			struct ValueAccessor<T*, ITypeInfo::RawPtr>
			{
				static Value BoxValue(T* object, ITypeDescriptor* typeDescriptor)
				{
					return Value::From(object);
				}

				static T* UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					if(value.IsNull()) return nullptr;
					T* result = nullptr;
					if (value.GetRawPtr())
					{
						result = value.GetRawPtr()->SafeAggregationCast<T>();
					}
					if(!result)
					{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
						if(!typeDescriptor)
						{
							typeDescriptor=GetTypeDescriptor<T>();
						}
						throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::RawPtr, value);
#else
						CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
					}
					return result;
				}
			};

			template<typename T>
			struct ValueAccessor<Ptr<T>, ITypeInfo::SharedPtr>
			{
				static Value BoxValue(Ptr<T> object, ITypeDescriptor* typeDescriptor)
				{
					return Value::From(object);
				}

				static Ptr<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					if (value.IsNull()) return nullptr;
					Ptr<T> result;
					if(value.GetValueType()==Value::RawPtr || value.GetValueType()==Value::SharedPtr)
					{
						result = Ptr(value.GetRawPtr()->SafeAggregationCast<T>());
					}
					if(!result)
					{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
						if(!typeDescriptor)
						{
							typeDescriptor=GetTypeDescriptor<T>();
						}
						throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::SharedPtr, value);
#else
						CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
					}
					return result;
				}
			};

			template<typename T>
			struct ValueAccessor<Nullable<T>, ITypeInfo::Nullable>
			{
				static Value BoxValue(Nullable<T> object, ITypeDescriptor* typeDescriptor)
				{
					return object?ValueAccessor<T, ITypeInfo::TypeDescriptor>::BoxValue(object.Value(), typeDescriptor):Value();
				}

				static Nullable<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					if(value.IsNull())
					{
						return Nullable<T>();
					}
					else
					{
						return ValueAccessor<T, ITypeInfo::TypeDescriptor>::UnboxValue(value, typeDescriptor, valueName);
					}
				}
			};

			template<typename T>
			struct ValueAccessor<T, ITypeInfo::TypeDescriptor>
			{
				static Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor)
				{
					using Type = std::remove_cvref_t<T>;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
					if(!typeDescriptor)
					{
						typeDescriptor = GetTypeDescriptor<Type>();
					}
#endif
					return Value::From(Ptr(new IValueType::TypedBox<Type>(object)), typeDescriptor);
				}

				static T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					using Type = std::remove_cvref_t<T>;
					if (auto unboxedValue = value.GetBoxedValue().Cast<IValueType::TypedBox<Type>>())
					{
						return unboxedValue->value;
					}
					else
					{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
						if (!typeDescriptor)
						{
							typeDescriptor = GetTypeDescriptor<Type>();
						}
						throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::BoxedValue, value);
#else
						CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
#endif
					}
				}
			};

			template<>
			struct ValueAccessor<Value, ITypeInfo::TypeDescriptor>
			{
				static Value BoxValue(const Value& object, ITypeDescriptor* typeDescriptor)
				{
					return object;
				}

				static Value UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return value;
				}
			};

			template<>
			struct ValueAccessor<VoidValue, ITypeInfo::TypeDescriptor>
			{
				static Value BoxValue(const VoidValue& object, ITypeDescriptor* typeDescriptor)
				{
					return Value();
				}

				static VoidValue UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return VoidValue();
				}
			};
		}
	}
}

#endif


/***********************************************************************
.\BOXING\BOXINGPARAMETER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER


namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
BoxParameter, UnboxParameter
***********************************************************************/

			template<typename T, TypeFlags Flag>
			struct ParameterAccessor
			{
			};
			
			/// <summary>Box an reflectable object. It supports generic types such as containers, functions (should be Func&lt;T&gt;), etc.</summary>
			/// <returns>The boxed value.</returns>
			/// <typeparam name="T">Type of the object.</typeparam>
			/// <param name="object">The object to box.</param>
			/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
			template<typename T>
			Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor)
			{
				using TIR = TypeInfoRetriver<std::remove_reference_t<T>>;
				return ParameterAccessor<std::remove_reference_t<T>, TIR::TypeFlag>::BoxParameter(object, typeDescriptor);
			}
			
			/// <summary>Box an reflectable object. It supports generic types such as containers, functions (should be Func&lt;T&gt;), etc.</summary>
			/// <typeparam name="T">Type of the object.</typeparam>
			/// <returns>The unboxed object. It could be the same object that is boxed, or it could be a new object.</returns>
			/// <param name="value">The value to unbox.</param>
			/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
			/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
			template<typename T>
			Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor , const WString& valueName)
			{
				using TIR = TypeInfoRetriver<std::remove_reference_t<T>>;
				return ParameterAccessor<T, TIR::TypeFlag>::UnboxParameter(value, typeDescriptor, valueName);
			}

/***********************************************************************
BoxParametersToList
***********************************************************************/

			inline void BoxParametersToList(Ptr<IValueList> arguments) {}

			template<typename T0, typename ...TArgs>
			void BoxParametersToList(Ptr<IValueList> arguments, T0&& p0, TArgs&& ...args)
			{
				arguments->Add(description::BoxParameter(p0));
				BoxParametersToList(arguments, args...);
			}

			class Value_xs
			{
			protected:
				collections::Array<Value>	arguments;
			public:
				Value_xs()
				{
				}

				template<typename T>
				Value_xs& operator,(T& value)
				{
					arguments.Resize(arguments.Count() + 1);
					arguments[arguments.Count() - 1] = BoxParameter(value);
					return *this;
				}

				Value_xs& operator,(const Value& value)
				{
					arguments.Resize(arguments.Count() + 1);
					arguments[arguments.Count() - 1] = value;
					return *this;
				}

				operator collections::Array<Value>& ()
				{
					return arguments;
				}
			};
 
/***********************************************************************
Basic Types
***********************************************************************/

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::NonGenericType>
			{
				static Value BoxParameter(const T& object, ITypeDescriptor* typeDescriptor)
				{
					return BoxValue<T>(object, typeDescriptor);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return { new T(std::move(UnboxValue<T>(value, typeDescriptor, valueName))), true };
				}
			};
		}
	}
}

#endif


/***********************************************************************
.\BOXING\INVOKEWITHBOXEDPARAMETERS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_BOXING_INVOKEWITHBOXEDPARAMETERS
#define VCZH_REFLECTION_BOXING_INVOKEWITHBOXEDPARAMETERS
 
 
namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
UnboxAndCall
***********************************************************************/

			namespace unboxcall_helper
			{
				template<typename T, vint I>
				struct ArgPack
				{
					using TArg = T;
					static const vint Index = I;
				};

				template<typename ...TArgs>
				struct ArgPacks
				{
				};

				template<typename TArgPacks, typename ...TArgs>
				struct MakeArgPacks_;

				template<typename ...TPacked>
				struct MakeArgPacks_<ArgPacks<TPacked...>>
				{
					using Type = ArgPacks<TPacked...>;
				};

				template<typename ...TPacked, typename T0, typename ...TArgs>
				struct MakeArgPacks_<ArgPacks<TPacked...>, T0, TArgs...>
				{
					using Type = typename MakeArgPacks_<ArgPacks<TPacked..., ArgPack<T0, sizeof...(TPacked)>>, TArgs...>::Type;
				};
			}

			template<typename ...TArgs>
			using MakeArgPacks = typename unboxcall_helper::MakeArgPacks_<unboxcall_helper::ArgPacks<>, TArgs...>::Type;

			namespace unboxcall_helper
			{
				template<typename TArgPacks>
				struct Unbox;

				template<typename ...TArgPacks>
				struct Unbox<ArgPacks<TArgPacks...>>
				{
					template<typename TFunction>
					static auto AndCallObject(TFunction&& function, IMethodInfo* methodInfo, const Ptr<IValueReadonlyList>& arguments) -> decltype(function(std::declval<typename TArgPacks::TArg>()...))
					{
						// function(arguments)
						return function(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
							arguments->Get(TArgPacks::Index),
							(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
							).Ref()...);
					}

					template<typename TFunction>
					static auto AndCallFunction(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments) -> decltype(function(std::declval<typename TArgPacks::TArg>()...))
					{
						// function(arguments)
						return function(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
							arguments[TArgPacks::Index],
							(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
							).Ref()...);
					}

					template<typename TClass, typename TFunction>
					static auto AndCallMethod(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments, TClass* object) -> decltype((object->*function)(std::declval<typename TArgPacks::TArg>()...))
					{
						// (object->*function)(arguments)
						return (object->*function)(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
							arguments[TArgPacks::Index],
							(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
							).Ref()...);
					}

					template<typename TClass, typename TFunction>
					static auto AndCallExternal(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments, TClass* object) -> decltype(function(object, std::declval<typename TArgPacks::TArg>()...))
					{
						// function(object, arguments)
						return function(
							object,
							UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
								arguments[TArgPacks::Index],
								(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
								).Ref()...
							);
					}

					template<typename TClass, typename R>
					static R AndNew(IMethodInfo* methodInfo, collections::Array<Value>& arguments)
					{
						// new TClass(arguments)
						return R(new TClass(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
							arguments[TArgPacks::Index],
							(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
							).Ref()...));
					}
				};
			}

/***********************************************************************
Invoke
***********************************************************************/

			namespace invoke_helper
			{
				template<typename TClass, typename R, typename ...TArgs>
				Value InvokeMethod(TClass* object, R(__thiscall TClass::* method)(TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
				{
					using TArgPacks = MakeArgPacks<TArgs...>;
					if constexpr (std::is_same_v<R, void>)
					{
						unboxcall_helper::Unbox<TArgPacks>::AndCallMethod(method, methodInfo, arguments, object);
						return {};
					}
					else
					{
						auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
						return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallMethod(method, methodInfo, arguments, object), td);
					}
				}

				template<typename TClass, typename R, typename ...TArgs>
				Value InvokeExternal(TClass* object, R(*method)(TClass*, TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
				{
					using TArgPacks = MakeArgPacks<TArgs...>;
					if constexpr (std::is_same_v<R, void>)
					{
						unboxcall_helper::Unbox<TArgPacks>::AndCallExternal(method, methodInfo, arguments, object);
						return {};
					}
					else
					{
						auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
						return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallExternal(method, methodInfo, arguments, object), td);
					}
				}

				template<typename R, typename ...TArgs>
				Value InvokeFunction(R(*method)(TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
				{
					using TArgPacks = MakeArgPacks<TArgs...>;
					if constexpr (std::is_same_v<R, void>)
					{
						unboxcall_helper::Unbox<TArgPacks>::AndCallFunction(method, methodInfo, arguments);
						return {};
					}
					else
					{
						auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
						return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallFunction(method, methodInfo, arguments), td);
					}
				}

				template<typename TFunction, typename ...TArgs>
				Value InvokeObject(TFunction& function, IMethodInfo* methodInfo, const Ptr<IValueReadonlyList>& arguments)
				{
					using TArgPacks = MakeArgPacks<TArgs...>;
					using TResult = decltype(unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments));
					if constexpr (std::is_same_v<TResult, void>)
					{
						unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments);
						return {};
					}
					else
					{
						auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
						return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments), td);
					}
				}
			}
		}
	}
}

#endif

/***********************************************************************
.\WRAPPERS\CONTAINERWRAPPERS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_WRAPPERS_CONTAINERWRAPPERS
#define VCZH_REFLECTION_WRAPPERS_CONTAINERWRAPPERS
 
 
namespace vl
{
	namespace reflection
	{
		namespace description
		{

/***********************************************************************
Enumerable Wrappers
***********************************************************************/

			template<typename T>
			class TypedEnumerator : public Object, public collections::IEnumerator<T>
			{
			private:
				Ptr<IValueEnumerable>		enumerable;
				Ptr<IValueEnumerator>		enumerator;
				vint						index;
				T							value;

			public:
				TypedEnumerator(Ptr<IValueEnumerable> _enumerable, vint _index, const T& _value)
					:enumerable(_enumerable)
					,index(_index)
					,value(_value)
				{
					enumerator=enumerable->CreateEnumerator();
					vint current=-1;
					while(current++<index)
					{
						enumerator->Next();
					}
				}

				TypedEnumerator(Ptr<IValueEnumerable> _enumerable)
					:enumerable(_enumerable)
					,index(-1)
				{
					Reset();
				}

				collections::IEnumerator<T>* Clone()const override
				{
					return new TypedEnumerator<T>(enumerable, index, value);
				}

				const T& Current()const override
				{
					return value;
				}

				vint Index()const override
				{
					return index;
				}

				bool Next() override
				{
					if(enumerator->Next())
					{
						index++;
						value=UnboxValue<T>(enumerator->GetCurrent());
						return true;
					}
					else
					{
						return false;
					}
				}

				void Reset() override
				{
					index=-1;
					enumerator=enumerable->CreateEnumerator();
				}
			};

			/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="T">The expected element type.</typeparam>
			/// <param name="value">The reflectable container.</param>
			template<typename T>
			collections::LazyList<T> GetLazyList(Ptr<IValueEnumerable> value)
			{
				return collections::LazyList<T>(new TypedEnumerator<T>(value));
			}

			/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="T">The expected element type.</typeparam>
			/// <param name="value">The reflectable container.</param>
			template<typename T>
			collections::LazyList<T> GetLazyList(Ptr<IValueReadonlyList> value)
			{
				return collections::Range<vint>(0, value->GetCount())
					.Select([value](vint i)
					{
						return UnboxValue<T>(value->Get(i));
					});
			}

			/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="T">The expected element type.</typeparam>
			/// <param name="value">The reflectable container.</param>
			template<typename T>
			collections::LazyList<T> GetLazyList(Ptr<IValueArray> value)
			{
				return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
			}

			/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="T">The expected element type.</typeparam>
			/// <param name="value">The reflectable container.</param>
			template<typename T>
			collections::LazyList<T> GetLazyList(Ptr<IValueList> value)
			{
				return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
			}

			/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="T">The expected element type.</typeparam>
			/// <param name="value">The reflectable container.</param>
			template<typename T>
			collections::LazyList<T> GetLazyList(Ptr<IValueObservableList> value)
			{
				return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
			}

			/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="K">The expected key type.</typeparam>
			/// <typeparam name="V">The expected value type.</typeparam>
			/// <param name="value">The reflectable dictionary.</param>
			template<typename K, typename V>
			collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueReadonlyDictionary> value)
			{
				return collections::Range<vint>(0, value->GetCount())
					.Select([value](vint i)
					{
						return collections::Pair<K, V>(UnboxValue<K>(value->GetKeys()->Get(i)), UnboxValue<V>(value->GetValues()->Get(i)));
					});
			}

			/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
			/// <returns>The created lazy list.</returns>
			/// <typeparam name="K">The expected key type.</typeparam>
			/// <typeparam name="V">The expected value type.</typeparam>
			/// <param name="value">The reflectable dictionary.</param>
			template<typename K, typename V>
			collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueDictionary> value)
			{
				return GetLazyList<K, V>(Ptr<IValueReadonlyDictionary>(value));
			}

/***********************************************************************
Collection Wrappers
***********************************************************************/

			namespace trait_helper
			{
				template<typename T>
				struct RemovePtr
				{
					typedef T					Type;
				};
				
				template<typename T>
				struct RemovePtr<T*>
				{
					typedef T					Type;
				};
				
				template<typename T>
				struct RemovePtr<Ptr<T>>
				{
					typedef T					Type;
				};
			}

#pragma warning(push)
#pragma warning(disable:4250)

			template<typename TCallback>
			auto ConvertCollectionError(TCallback&& callback) -> decltype(callback())
			{
				try
				{
					return callback();
				}
				catch (const Error& ex)
				{
					throw Exception(WString::Unmanaged(ex.Description()));
				}
			}

			template<typename T>
			class ValueEnumerableWrapper;

			template<typename TWrapper, typename TEnumerator>
			class ValueEnumeratorWrapper : public Object, public virtual IValueEnumerator
			{
			protected:
				typedef typename trait_helper::RemovePtr<TEnumerator>::Type		ContainerType;
				typedef typename ContainerType::ElementType						ElementType;

				Ptr<TWrapper>					enumerableWrapper;
				TEnumerator						wrapperPointer;
			public:
				ValueEnumeratorWrapper(const Ptr<TWrapper>& _enumerableWrapper, const TEnumerator& _wrapperPointer)
					:enumerableWrapper(_enumerableWrapper)
					, wrapperPointer(_wrapperPointer)
				{
				}

				Value GetCurrent()override
				{
					if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
					return ConvertCollectionError([&]()
					{
						return BoxValue<ElementType>(wrapperPointer->Current());
					});
				}

				vint GetIndex()override
				{
					if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
					return wrapperPointer->Index();
				}

				bool Next()override
				{
					if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
					return ConvertCollectionError([&]()
					{
						return wrapperPointer->Next();
					});
				}
			};

#define WRAPPER_POINTER this->wrapperPointer
#define ENSURE_WRAPPER_POINTER if (!WRAPPER_POINTER) throw ObjectDisposedException()

			template<typename T>
			class ValueEnumerableWrapper : public Object, public virtual collections::ICollectionReference, public virtual IValueEnumerable
			{
				template<typename TWrapper, typename TEnumerator>
				friend class ValueEnumeratorWrapper;
			protected:
				typedef typename trait_helper::RemovePtr<T>::Type		ContainerType;
				typedef typename ContainerType::ElementType				ElementType;

				T								wrapperPointer;
			public:
				ValueEnumerableWrapper(const T& _wrapperPointer)
					:wrapperPointer(_wrapperPointer)
				{
				}

				void OnDisposed()override
				{
					wrapperPointer = nullptr;
				}

				Ptr<IValueEnumerator> CreateEnumerator()override
				{
					ENSURE_WRAPPER_POINTER;
					return Ptr(new ValueEnumeratorWrapper<
						ValueEnumerableWrapper<T>,
						Ptr<collections::IEnumerator<ElementType>>
					>(
						Ptr(this),
						Ptr(wrapperPointer->CreateEnumerator())
					));
				}

				const Object* GetCollectionObject()override
				{
					if constexpr (std::is_same_v<typename trait_helper::RemovePtr<T>::Type*, T>)
					{
						if (wrapperPointer->GetCollectionReference() == this)
						{
							return wrapperPointer;
						}
						else
						{
							return nullptr;
						}
					}
					else
					{
						return nullptr;
					}
				}
			};

			template<typename T>
			class ValueReadonlyListWrapper : public ValueEnumerableWrapper<T>, public virtual IValueReadonlyList
			{
			protected:
				typedef typename trait_helper::RemovePtr<T>::Type		ContainerType;
				typedef typename ContainerType::ElementType				ElementType;
				typedef typename KeyType<ElementType>::Type				ElementKeyType;

			public:
				ValueReadonlyListWrapper(const T& _wrapperPointer)
					:ValueEnumerableWrapper<T>(_wrapperPointer)
				{
				}

				vint GetCount()override
				{
					ENSURE_WRAPPER_POINTER;
					return WRAPPER_POINTER->Count();
				}

				Value Get(vint index)override
				{
					ENSURE_WRAPPER_POINTER;
					return ConvertCollectionError([&]()
					{
						return BoxValue<ElementType>(WRAPPER_POINTER->Get(index));
					});
				}

				bool Contains(const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementKeyType item = UnboxValue<ElementKeyType>(value);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->Contains(item);
					});
				}

				vint IndexOf(const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementKeyType item = UnboxValue<ElementKeyType>(value);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->IndexOf(item);
					});
				}
			};

			template<typename T>
			class ValueArrayWrapper : public ValueReadonlyListWrapper<T>, public virtual IValueArray
			{
			protected:
				typedef typename trait_helper::RemovePtr<T>::Type		ContainerType;
				typedef typename ContainerType::ElementType				ElementType;
				typedef typename KeyType<ElementType>::Type				ElementKeyType;

			public:
				ValueArrayWrapper(const T& _wrapperPointer)
					:ValueReadonlyListWrapper<T>(_wrapperPointer)
				{
				}

				void Set(vint index, const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementType item = UnboxValue<ElementType>(value);
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Set(index, item);
					});
				}

				void Resize(vint size)override
				{
					ENSURE_WRAPPER_POINTER;
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Resize(size);
					});
				}
			};

			template<typename T>
			class ValueListWrapper : public ValueReadonlyListWrapper<T>, public virtual IValueList
			{
			protected:
				typedef typename trait_helper::RemovePtr<T>::Type		ContainerType;
				typedef typename ContainerType::ElementType				ElementType;
				typedef typename KeyType<ElementType>::Type				ElementKeyType;

			public:
				ValueListWrapper(const T& _wrapperPointer)
					:ValueReadonlyListWrapper<T>(_wrapperPointer)
				{
				}

				void Set(vint index, const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementType item = UnboxValue<ElementType>(value);
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Set(index, item);
					});
				}

				vint Add(const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementType item = UnboxValue<ElementType>(value);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->Add(item);
					});
				}

				vint Insert(vint index, const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementType item = UnboxValue<ElementType>(value);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->Insert(index, item);
					});
				}

				bool Remove(const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					ElementKeyType item = UnboxValue<ElementKeyType>(value);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->Remove(item);
					});
				}

				bool RemoveAt(vint index)override
				{
					ENSURE_WRAPPER_POINTER;
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->RemoveAt(index);
					});
				}

				void Clear()override
				{
					ENSURE_WRAPPER_POINTER;
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Clear();
					});
				}
			};

			template<typename T>
			class ValueObservableListWrapper : public ValueListWrapper<T>, public virtual IValueObservableList
			{
			public:
				ValueObservableListWrapper(const T& _wrapperPointer)
					:ValueListWrapper<T>(_wrapperPointer)
				{
				}
			};

			template<typename T>
			class ValueReadonlyDictionaryWrapper : public virtual Object, public virtual collections::ICollectionReference, public virtual IValueReadonlyDictionary
			{
			protected:
				typedef typename trait_helper::RemovePtr<T>::Type		ContainerType;
				typedef typename ContainerType::KeyContainer			KeyContainer;
				typedef typename ContainerType::ValueContainer			ValueContainer;
				typedef typename KeyContainer::ElementType				KeyValueType;
				typedef typename KeyType<KeyValueType>::Type			KeyKeyType;
				typedef typename ValueContainer::ElementType			ValueType;

				T								wrapperPointer;
				Ptr<IValueReadonlyList>			keys;
				Ptr<IValueReadonlyList>			values;
			public:
				ValueReadonlyDictionaryWrapper(const T& _wrapperPointer)
					:wrapperPointer(_wrapperPointer)
				{
				}

				void OnDisposed()override
				{
					wrapperPointer = nullptr;
					keys = nullptr;
					values = nullptr;
				}

				Ptr<IValueReadonlyList> GetKeys()override
				{
					ENSURE_WRAPPER_POINTER;
					if (!keys)
					{
						keys = UnboxValue<Ptr<IValueReadonlyList>>(BoxParameter(wrapperPointer->Keys()));
					}
					return keys;
				}

				Ptr<IValueReadonlyList> GetValues()override
				{
					ENSURE_WRAPPER_POINTER;
					if (!values)
					{
						values = UnboxValue<Ptr<IValueReadonlyList>>(BoxParameter(wrapperPointer->Values()));
					}
					return values;
				}

				vint GetCount()override
				{
					ENSURE_WRAPPER_POINTER;
					return wrapperPointer->Count();
				}

				Value Get(const Value& key)override
				{
					ENSURE_WRAPPER_POINTER;
					KeyKeyType item = UnboxValue<KeyKeyType>(key);
					return ConvertCollectionError([&]()
					{
						ValueType result = wrapperPointer->Get(item);
						return BoxValue<ValueType>(result);
					});
				}

				const Object* GetCollectionObject()override
				{
					if constexpr (std::is_same_v<typename trait_helper::RemovePtr<T>::Type*, T>)
					{
						if (wrapperPointer->GetCollectionReference() == this)
						{
							return wrapperPointer;
						}
						else
						{
							return nullptr;
						}
					}
					else
					{
						return nullptr;
					}
				}
			};

#define KEY_VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyValueType
#define VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::ValueType
#define KEY_KEY_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyKeyType
			
			template<typename T>
			class ValueDictionaryWrapper : public virtual ValueReadonlyDictionaryWrapper<T>, public virtual IValueDictionary
			{
			public:
				ValueDictionaryWrapper(const T& _wrapperPointer)
					:ValueReadonlyDictionaryWrapper<T>(_wrapperPointer)
				{
				}

				void Set(const Value& key, const Value& value)override
				{
					ENSURE_WRAPPER_POINTER;
					KEY_VALUE_TYPE item = UnboxValue<KEY_VALUE_TYPE>(key);
					VALUE_TYPE result = UnboxValue<VALUE_TYPE>(value);
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Set(item, result);
					});
				}

				bool Remove(const Value& key)override
				{
					ENSURE_WRAPPER_POINTER;
					KEY_KEY_TYPE item = UnboxValue<KEY_KEY_TYPE>(key);
					return ConvertCollectionError([&]()
					{
						return WRAPPER_POINTER->Remove(item);
					});
				}

				void Clear()override
				{
					ENSURE_WRAPPER_POINTER;
					ConvertCollectionError([&]()
					{
						WRAPPER_POINTER->Clear();
					});
				}
			};
#undef KEY_VALUE_TYPE
#undef VALUE_TYPE
#undef KEY_KEY_TYPE

#undef ENSURE_WRAPPER_POINTER
#undef WRAPPER_POINTER
#pragma warning(pop)
		}
	}

	namespace collections
	{
		template<typename T>
		void ObservableList<T>::NotifyUpdateInternal(vint start, vint count, vint newCount)
		{
			if (auto colref = this->template TryGetCollectionReference<reflection::description::IValueObservableList>())
			{
				colref->ItemChanged(start, count, newCount);
			}
		}
	}
}

#endif


/***********************************************************************
.\BOXING\BOXINGPARAMETER_CONTAINERS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER_CONTAINERS
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER_CONTAINERS


namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
Containers
***********************************************************************/

			template<typename TValueItf, typename TExpectedItf, template<typename T> class TValueImpl, typename T>
			auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t<std::is_convertible_v<TValueItf*, TExpectedItf*>, Ptr<TExpectedItf>>
			{
				auto colref = collection->template TryGetCollectionReference<TValueImpl<T*>>();
				if (colref) return colref;
				colref = Ptr(new TValueImpl<T*>(collection));
				collection->SetCollectionReference(colref);
				return colref;
			}

			template<typename TValueItf, typename TExpectedItf, template<typename T> class TValueImpl, typename T>
			auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t<!std::is_convertible_v<TValueItf*, TExpectedItf*>, Ptr<TExpectedItf>>
			{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				throw ArgumentTypeMismtatchException(
					WString::Unmanaged(L"collection"),
					Description<TExpectedItf>::GetAssociatedTypeDescriptor(),
					Description<TValueItf>::GetAssociatedTypeDescriptor()
					);
#else
				CHECK_FAIL(L"vl::reflection::description::GetValueCollectionFromCollection()#Argument type mismatch.");
#endif
			}

			template<typename TValueItf, typename T>
			Ptr<TValueItf> ChooseValueCollectionFromNonDictionaryEnumerable(const collections::IEnumerable<T>* enumerable)
			{
				auto writable = const_cast<Object*>(enumerable->GetCollectionObject());
				if (auto xs = dynamic_cast<collections::ObservableList<std::remove_cvref_t<T>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueObservableList, TValueItf, ValueObservableListWrapper>(xs);
				}
				else if (auto xs = dynamic_cast<collections::ObservableListBase<std::remove_cvref_t<T>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueList, TValueItf, ValueListWrapper>(xs);
				}
				else if (auto xs = dynamic_cast<collections::List<std::remove_cvref_t<T>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueList, TValueItf, ValueListWrapper>(xs);
				}
				else if (auto xs = dynamic_cast<collections::Array<std::remove_cvref_t<T>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueArray, TValueItf, ValueArrayWrapper>(xs);
				}
				else if (auto xs = dynamic_cast<collections::SortedList<std::remove_cvref_t<T>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueReadonlyList, TValueItf, ValueReadonlyListWrapper>(xs);
				}
				else
				{
					return GetValueCollectionFromCollection<IValueEnumerable, TValueItf, ValueEnumerableWrapper>(xs);
				}
			}

			template<typename TValueItf, typename T>
			Ptr<TValueItf> ChooseValueCollectionFromEnumerable(const collections::IEnumerable<T>* enumerable)
			{
				return ChooseValueCollectionFromNonDictionaryEnumerable<TValueItf>(enumerable);
			}

			template<typename TValueItf, typename K, typename V>
			Ptr<TValueItf> ChooseValueCollectionFromEnumerable(const collections::IEnumerable<collections::Pair<K, V>>* enumerable)
			{
				auto writable = const_cast<Object*>(enumerable->GetCollectionObject());
				if (auto xs = dynamic_cast<collections::Dictionary<std::remove_cvref_t<K>, std::remove_cvref_t<V>>*>(writable))
				{
					return GetValueCollectionFromCollection<IValueDictionary, TValueItf, ValueDictionaryWrapper>(xs);
				}
				else
				{
					return ChooseValueCollectionFromNonDictionaryEnumerable<TValueItf>(enumerable);
				}
			}

			template<typename TValueItf, typename T>
			Value GetValueFromEnumerable(const collections::IEnumerable<T>& enumerable)
			{
				auto result = ChooseValueCollectionFromEnumerable<TValueItf>(&enumerable);
				ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
				td = Description<TValueItf>::GetAssociatedTypeDescriptor();
#endif
				return BoxValue(result, td);
			}

			template<typename T, typename TValueItf>
			Unboxed<T> UnboxCollection(const Ptr<TValueItf>& colref)
			{
				using TCollection = std::remove_const_t<T>;
				if (auto colobj = dynamic_cast<TCollection*>(const_cast<Object*>(colref->GetCollectionObject())))
				{
					return { colobj,false };
				}
				else
				{
					auto collection = new TCollection();
					auto lazyList = GetLazyList<typename TCollection::ElementType>(colref);
					collections::CopyFrom(*collection, lazyList);
					return { collection, true };
				}
			}

			template<typename T, typename TValueItf>
			Unboxed<T> UnboxDictionary(const Ptr<TValueItf>& colref)
			{
				using TCollection = std::remove_const_t<T>;
				if (auto colobj = dynamic_cast<TCollection*>(const_cast<Object*>(colref->GetCollectionObject())))
				{
					return { colobj,false };
				}
				else
				{
					auto collection = new TCollection();
					auto lazyList = GetLazyList<
						typename TCollection::KeyContainer::ElementType,
						typename TCollection::ValueContainer::ElementType
					>(colref);
					collections::CopyFrom(*collection, lazyList);
					return { collection, true };
				}
			}

			template<typename T>
			struct ParameterAccessor<const collections::LazyList<T>, TypeFlags::EnumerableType>
			{
				static Value BoxParameter(const collections::LazyList<T>& object, ITypeDescriptor* typeDescriptor)
				{
					Ptr<IValueEnumerable> result = IValueEnumerable::Create(
						collections::From(object)
						.Select([](const T& item)
							{
								return BoxValue<T>(item);
							})
					);

					ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
					td = Description<IValueEnumerable>::GetAssociatedTypeDescriptor();
#endif
					return BoxValue(result, td);
				}
			};

			template<typename T>
			struct ParameterAccessor<collections::LazyList<T>, TypeFlags::EnumerableType>
			{
				static Value BoxParameter(collections::LazyList<T>& object, ITypeDescriptor* typeDescriptor)
				{
					return ParameterAccessor<const collections::LazyList<T>, TypeFlags::EnumerableType>::BoxParameter(object, typeDescriptor);
				}

				static Unboxed<collections::LazyList<T>> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					typedef typename collections::LazyList<T>::ElementType ElementType;
					Ptr<IValueEnumerable> listProxy = UnboxValue<Ptr<IValueEnumerable>>(value, typeDescriptor, valueName);
					return { new collections::LazyList<T>(std::move(GetLazyList<T>(listProxy))), true };
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::ReadonlyListType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueReadonlyList>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxCollection<T>(UnboxValue<Ptr<IValueReadonlyList>>(value, typeDescriptor, valueName));
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::ArrayType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueArray>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxCollection<T>(UnboxValue<Ptr<IValueArray>>(value, typeDescriptor, valueName));
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::ListType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueList>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxCollection<T>(UnboxValue<Ptr<IValueList>>(value, typeDescriptor, valueName));
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::ObservableListType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueObservableList>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxCollection<T>(UnboxValue<Ptr<IValueObservableList>>(value, typeDescriptor, valueName));
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::ReadonlyDictionaryType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueReadonlyDictionary>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxDictionary<T>(UnboxValue<Ptr<IValueReadonlyDictionary>>(value, typeDescriptor, valueName));
				}
			};

			template<typename T>
			struct ParameterAccessor<T, TypeFlags::DictionaryType>
			{
				static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
				{
					return GetValueFromEnumerable<IValueDictionary>(object);
				}

				static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					return UnboxDictionary<T>(UnboxValue<Ptr<IValueDictionary>>(value, typeDescriptor, valueName));
				}
			};
		}
	}
}

#endif


/***********************************************************************
.\WRAPPERS\FUNCTIONWRAPPERS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_WRAPPERS_FUNCTIONWRAPPERS
#define VCZH_REFLECTION_WRAPPERS_FUNCTIONWRAPPERS
 
 
namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
Function Wrappers
***********************************************************************/

			template<typename T>
			class ValueFunctionProxyWrapper
			{
			};

			template<typename R, typename ...TArgs>
			class ValueFunctionProxyWrapper<R(TArgs...)> : public Object, public virtual IValueFunctionProxy
			{
				typedef Func<R(TArgs...)>					FunctionType;
			protected:
				FunctionType			function;

			public:
				ValueFunctionProxyWrapper(const FunctionType& _function)
					:function(_function)
				{
				}

				FunctionType GetFunction()
				{
					return function;
				}

				Value Invoke(Ptr<IValueReadonlyList> arguments)override
				{
					if (!arguments || arguments->GetCount() != sizeof...(TArgs))
					{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
						throw ArgumentCountMismtatchException();
#else
						CHECK_FAIL(L"Argument count mismatch.");
#endif
					}
					return invoke_helper::InvokeObject<FunctionType, TArgs...>(function, nullptr, arguments);
				}
			};
		}
	}
}

#endif

/***********************************************************************
.\BOXING\BOXINGPARAMETER_FUNCTIONS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER_FUNCTIONS
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER_FUNCTIONS


namespace vl
{
	namespace reflection
	{
		namespace description
		{
/***********************************************************************
Functions
***********************************************************************/

			template<typename R, typename ...TArgs>
			struct ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
			{
				static Value BoxParameter(const Func<R(TArgs...)>& object, ITypeDescriptor* typeDescriptor)
				{
					typedef R(RawFunctionType)(TArgs...);
					Ptr<IValueFunctionProxy> result=Ptr(new ValueFunctionProxyWrapper<RawFunctionType>(object));

					ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
					td = Description<IValueFunctionProxy>::GetAssociatedTypeDescriptor();
#endif
					return BoxValue<Ptr<IValueFunctionProxy>>(result, td);
				}
 
				static Unboxed<Func<R(TArgs...)>> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
				{
					typedef R(RawFunctionType)(TArgs...);
					typedef Func<R(TArgs...)> FunctionType;
					typedef ValueFunctionProxyWrapper<RawFunctionType> ProxyType;
					if (auto functionProxy = UnboxValue<Ptr<IValueFunctionProxy>>(value, typeDescriptor, valueName))
					{
						if (auto proxy = functionProxy.Cast<ProxyType>())
						{
							return { new FunctionType(std::move(proxy->GetFunction())), true };
						}
						else
						{
							return { new FunctionType([functionProxy](TArgs ...args)
							{
								Ptr<IValueList> arguments = IValueList::Create();
								BoxParametersToList(arguments, std::forward<TArgs>(args)...);
								auto result = functionProxy->Invoke(arguments);
								if constexpr (!std::is_same_v<R, void>)
								{
									auto unboxed = description::UnboxParameter<std::remove_cvref_t<R>>(result);
									if (std::is_reference_v<R>)
									{
										CHECK_ERROR(!unboxed.IsOwned(), L"It is impossible to return a reference from a unboxed value, when the unboxing has to call new T(...).");
									}
									return unboxed.Ref();
								}
							}), true };
						}
					}
					else
					{
						return { new FunctionType(),true };
					}
				}
			};
 
			template<typename R, typename ...TArgs>
			struct ParameterAccessor<const Func<R(TArgs...)>, TypeFlags::FunctionType> : ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
			{
			};
		}
	}
}

#endif


/***********************************************************************
.\BOXING\BOXING.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_BOXING_BOXING
#define VCZH_REFLECTION_BOXING_BOXING


#endif


/***********************************************************************
.\METADATA\METADATA_MEMBER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_METADATA_METADATA_MEMBER
#define VCZH_REFLECTION_METADATA_METADATA_MEMBER


namespace vl
{
	namespace reflection
	{
		namespace description
		{ 
/***********************************************************************
ConstructorArgumentAdder
***********************************************************************/

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
			
			namespace internal_helper
			{
				template<typename T>
				struct ConstructorArgumentAdder
				{
					static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
					{
					}
				};

				template<typename T0, typename ...TNextArgs>
				struct ConstructorArgumentAdder<TypeTuple<T0, TNextArgs...>>
				{
					static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
					{
						methodInfo->AddParameter(Ptr(new ParameterInfoImpl(methodInfo, parameterNames[index], TypeInfoRetriver<T0>::CreateTypeInfo())));
						ConstructorArgumentAdder<TypeTuple<TNextArgs...>>::Add(methodInfo, parameterNames, index + 1);
					}
				};
			}
 
/***********************************************************************
MethodInfoImpl
***********************************************************************/
 
			template<typename T>
			class CustomConstructorInfoImpl{};
 
			template<typename TClass, typename T>
			class CustomMethodInfoImpl{};
 
			template<typename TClass, typename T>
			class CustomExternalMethodInfoImpl{};
 
			template<typename T>
			class CustomStaticMethodInfoImpl{};

			template<typename TClass, typename T>
			class CustomEventInfoImpl{};

#endif
		}
	}
}

#endif


/***********************************************************************
.\METADATA\METADATA_EVENT.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_METADATA_METADATA_EVENT
#define VCZH_REFLECTION_METADATA_METADATA_EVENT
 
 
namespace vl
{
	namespace reflection
	{
		namespace description
		{
			template<typename ...TArgs>
			struct EventHelper
			{
				using Handler = const Func<void(TArgs...)>&;

				class EventHandlerImpl : public Object, public reflection::description::IEventHandler
				{
				public:
					Ptr<EventHandler> handler;

					EventHandlerImpl(Ptr<EventHandler> _handler)
						:handler(_handler)
					{
					}

					bool IsAttached()override
					{
						return handler->IsAttached();
					}
				};

				static Ptr<reflection::description::IEventHandler> Attach(Event<void(TArgs...)>& e, Handler handler)
				{
					return Ptr(new EventHandlerImpl(e.Add(handler)));
				}

				static bool Detach(Event<void(TArgs...)>& e, Ptr<reflection::description::IEventHandler> handler)
				{
					auto impl = handler.Cast<EventHandlerImpl>();
					if (!impl) return false;
					return e.Remove(impl->handler);
				}

				static Event<void(TArgs...)>& Invoke(Event<void(TArgs...)>& e)
				{
					return e;
				}
			};

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
 
/***********************************************************************
CustomEventInfoImpl<void(TArgs...)>
***********************************************************************/

			template<typename TClass, typename ...TArgs>
			class CustomEventInfoImpl<TClass, void(TArgs...)> : public EventInfoImpl
			{
			protected:
				Event<void(TArgs...)> TClass::*			eventRef;

				Ptr<IEventHandler> AttachInternal(DescriptableObject* thisObject, Ptr<IValueFunctionProxy> handler)override
				{
					TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
					Event<void(TArgs...)>& eventObject = object->*eventRef;
					auto func = Func<void(TArgs...)>([=](TArgs ...args)
						{
							auto arguments = IValueList::Create();
							BoxParametersToList(arguments, std::forward<TArgs>(args)...);
							handler->Invoke(arguments);
						});
					return EventHelper<TArgs...>::Attach(eventObject, func);
				}

				bool DetachInternal(DescriptableObject* thisObject, Ptr<IEventHandler> handler)override
				{
					TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
					Event<void(TArgs...)>& eventObject = object->*eventRef;
					return EventHelper<TArgs...>::Detach(eventObject, handler);
				}

				void InvokeInternal(DescriptableObject* thisObject, Ptr<IValueReadonlyList> arguments)override
				{
					TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
					Event<void(TArgs...)>& eventObject = object->*eventRef;
					invoke_helper::InvokeObject<Event<void(TArgs...)>, TArgs...>(eventObject, nullptr, arguments);
				}

				Ptr<ITypeInfo> GetHandlerTypeInternal()override
				{
					return TypeInfoRetriver<Func<void(TArgs...)>>::CreateTypeInfo();
				}
			public:
				CustomEventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Event<void(TArgs...)> TClass::* _eventRef)
					:EventInfoImpl(_ownerTypeDescriptor, _name)
					, eventRef(_eventRef)
				{
				}

				~CustomEventInfoImpl()
				{
				}

				IEventInfo::ICpp* GetCpp()override
				{
					return nullptr;
				}
			};

			template<typename T>
			struct CustomEventFunctionTypeRetriver
			{
				typedef vint								Type;
			};

			template<typename TClass, typename TEvent>
			struct CustomEventFunctionTypeRetriver<Event<TEvent> TClass::*>
			{
				typedef TEvent								Type;
			};
#endif
		}
	}
}

#endif

/***********************************************************************
.\METADATA\METADATA_FUNCTION.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
 
#ifndef VCZH_REFLECTION_METADATA_METADATA_FUNCTION
#define VCZH_REFLECTION_METADATA_METADATA_FUNCTION
 
 
namespace vl
{
	namespace reflection
	{
		namespace description
		{

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
 
/***********************************************************************
CustomConstructorInfoImpl<R(TArgs...)>
***********************************************************************/

			template<typename R, typename ...TArgs>
			class CustomConstructorInfoImpl<R(TArgs...)> : public MethodInfoImpl
			{
				using TClass = typename trait_helper::RemovePtr<std::remove_cvref_t<R>>::Type;
			protected:

				Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
				{
					return BoxParameter(unboxcall_helper::Unbox<MakeArgPacks<TArgs...>>::template AndNew<TClass, R>(this, arguments));
				}
 
				Value CreateFunctionProxyInternal(const Value& thisObject)override
				{
					auto proxy = Func([](TArgs ...args)->R
					{
						R result = R(new TClass(args...));
						return result;
					});
					return BoxParameter(proxy);
				}
			public:
				CustomConstructorInfoImpl(const wchar_t* parameterNames[])
					:MethodInfoImpl(0, TypeInfoRetriver<R>::CreateTypeInfo(), true)
				{
					internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
				}

				IMethodInfo::ICpp* GetCpp()override
				{
					return nullptr;
				}
			};
 
/***********************************************************************
CustomMethodInfoImpl<TClass, R(TArgs...)>
CustomExternalMethodInfoImpl<TClass, R(TArgs...)>
***********************************************************************/

			class MethodInfoImpl_StaticCpp : public MethodInfoImpl, private IMethodInfo::ICpp
			{
			private:
				WString invokeTemplate;
				WString closureTemplate;

				const WString& GetInvokeTemplate()override
				{
					return invokeTemplate;
				}

				const WString& GetClosureTemplate()override
				{
					return closureTemplate;
				}
			public:
				MethodInfoImpl_StaticCpp(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic, const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
					:MethodInfoImpl(_ownerMethodGroup, _return, _isStatic)
				{
					CHECK_ERROR((_invokeTemplate == nullptr) == (_closureTemplate == nullptr), L"MethodInfoImpl_StaticCpp::MethodInfoImpl_StaticCpp()#Templates should all be set or default at the same time.");
					if (_invokeTemplate)
					{
						invokeTemplate = WString::Unmanaged(_invokeTemplate);
					}
					if (_closureTemplate)
					{
						closureTemplate = WString::Unmanaged(_closureTemplate);
					}
				}

				IMethodInfo::ICpp* GetCpp()override
				{
					return invokeTemplate.Length() == 0 || closureTemplate.Length() == 0 ? nullptr : this;
				}
			};

			template<typename TClass, typename R, typename ...TArgs>
			class CustomMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
			{
			protected:
				R(__thiscall TClass::* method)(TArgs...);
 
				Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
				{
					TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
					return invoke_helper::InvokeMethod<TClass, R, TArgs...>(object, method, this, arguments);
				}
 
				Value CreateFunctionProxyInternal(const Value& thisObject)override
				{
					TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
					Func<R(TArgs...)> proxy(object, method);
					return BoxParameter(proxy);
				}
			public:
				CustomMethodInfoImpl(const wchar_t* parameterNames[], R(__thiscall TClass::* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
					:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
					, method(_method)
				{
					internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
				}
			};
 
			template<typename TClass, typename R, typename ...TArgs>
			class CustomExternalMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
			{
			protected:
				R(*method)(TClass*, TArgs...);
 
				Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
				{
					TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
					return invoke_helper::InvokeExternal<TClass, R, TArgs...>(object, method, this, arguments);
				}
 
				Value CreateFunctionProxyInternal(const Value& thisObject)override
				{
					TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
					auto proxy = Func([object, this](TArgs... args)->decltype(auto) { return method(object, args...); });
					return BoxParameter(proxy);
				}
			public:
				CustomExternalMethodInfoImpl(const wchar_t* parameterNames[], R(*_method)(TClass*, TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
					:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
					, method(_method)
				{
					internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
				}
			};
 
/***********************************************************************
CustomStaticMethodInfoImpl<R(TArgs...)>
***********************************************************************/

			template<typename R, typename ...TArgs>
			class CustomStaticMethodInfoImpl<R(TArgs...)> : public MethodInfoImpl_StaticCpp
			{
			protected:
				R(* method)(TArgs...);
 
				Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
				{
					return invoke_helper::InvokeFunction<R, TArgs...>(method, this, arguments);
				}
 
				Value CreateFunctionProxyInternal(const Value& thisObject)override
				{
					Func<R(TArgs...)> proxy(method);
					return BoxParameter(proxy);
				}
			public:
				CustomStaticMethodInfoImpl(const wchar_t* parameterNames[], R(* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
					:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), true, _invokeTemplate, _closureTemplate)
					,method(_method)
				{
					internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
				}
			};
#endif
		}
	}
}

#endif

/***********************************************************************
.\REFLECTION\MACROS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_REFLECTION_MACROS
#define VCZH_REFLECTION_REFLECTION_MACROS


#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

/***********************************************************************
Macros
***********************************************************************/

namespace vl
{
	namespace reflection
	{
		namespace description
		{
			template<typename T>
			struct CustomTypeDescriptorSelector{};

			struct MethodPointerBinaryData
			{
				typedef collections::Dictionary<MethodPointerBinaryData, IMethodInfo*>		MethodMap;

				class IIndexer : public virtual IDescriptable
				{
				public:
					virtual void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo) = 0;
					virtual IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data) = 0;
				};

				vint data[4];

				friend std::strong_ordering operator<=>(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
				{
					for (vint i = 0; i < sizeof(data) / sizeof(*data); i++)
					{
						auto result = a.data[i] <=> b.data[i];
						if (result != 0) return result;
					}
					return std::strong_ordering::equal;
				}

				friend bool operator==(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
				{
					return (a <=> b) == 0;
				}
			};

			template<typename T>
			union MethodPointerBinaryDataRetriver
			{
				T methodPointer;
				MethodPointerBinaryData binaryData;

				MethodPointerBinaryDataRetriver(T _methodPointer)
				{
					memset(&binaryData, 0, sizeof(binaryData));
					methodPointer = _methodPointer;
				}

				const MethodPointerBinaryData& GetBinaryData()
				{
					static_assert(sizeof(T) <= sizeof(MethodPointerBinaryData), "Your C++ compiler is bad!");
					return binaryData;
				}
			};

			template<typename T, TypeDescriptorFlags TDFlags>
			struct MethodPointerBinaryDataRecorder
			{
				static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
				{
				}
			};

			template<typename T>
			struct MethodPointerBinaryDataRecorder<T, TypeDescriptorFlags::Interface>
			{
				static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
				{
					auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(td);
					CHECK_ERROR(impl != nullptr, L"Internal error: RecordMethod can only be called when registering methods.");
					impl->IndexMethodInfo(data, methodInfo);
				}
			};

			template<typename T>
			using FUNCTIONNAME_AddPointer = T*;

#ifndef VCZH_DEBUG_NO_REFLECTION

			namespace detail
			{
				namespace attribute_macro
				{
					template<typename TArg>
					struct BoxingProxy
					{
						AttributeInfoImpl* info;
						TArg&& value;

						template<typename FieldType>
						operator FieldType()
						{
							FieldType field(std::forward<TArg>(value));
							if constexpr (std::is_pointer_v<std::remove_cvref_t<FieldType>>)
							{
								using PointedType = std::remove_pointer_t<std::remove_cvref_t<FieldType>>;
								auto valueType = description::GetTypeDescriptor<PointedType>();
								auto boxed = BoxValue<std::remove_cvref_t<FieldType>>(field);
								info->AddValue(valueType, boxed);
							}
							else
							{
								auto boxed = BoxValue<std::remove_cvref_t<FieldType>>(field);
								auto valueType = boxed.GetTypeDescriptor();
								info->AddValue(valueType, boxed);
							}
							return field;
						}
					};

					template<typename TAttribute, typename... TArgs>
					Ptr<IAttributeInfo> MakeAttributeInfo(TArgs&&... args)
					{
						static_assert(requires { TAttribute{ std::forward<TArgs>(args)... }; }, "ATTRIBUTE_* requires TYPE{ARG1, ...} to compile.");

						auto attributeType = description::GetTypeDescriptor<TAttribute>();
						CHECK_ERROR(attributeType != nullptr, L"ATTRIBUTE_*#Failed to resolve the reflected attribute type.");
						CHECK_ERROR(attributeType->GetTypeDescriptorFlags() == TypeDescriptorFlags::Struct, L"ATTRIBUTE_*#Attribute type must be a reflected struct.");

						auto info = Ptr(new AttributeInfoImpl(attributeType));
						if constexpr (sizeof...(TArgs) > 0)
						{
							// Actual field types will be applied by calling BoxingProxy<TArgs>::operator FieldType() in the constructor
							// During the conversion, the expected attribute argument type can be retrieved to construct IAttributeInfo
							(void)TAttribute{ BoxingProxy<TArgs>{info.Obj(), std::forward<TArgs>(args)}... };
						}
						return info;
					}

					inline IParameterInfo* FindParameter(IMethodInfo* method, const WString& parameterName, const wchar_t* macroName)
					{
						vint matchedCount = 0;
						IParameterInfo* matchedParameter = nullptr;
						for (vint i = 0; i < method->GetParameterCount(); i++)
						{
							auto parameter = method->GetParameter(i);
							if (parameter->GetName() == parameterName)
							{
								matchedCount++;
								matchedParameter = parameter;
							}
						}

						CHECK_ERROR(matchedCount != 0, (WString::Unmanaged(macroName) + L"#The named parameter does not exist on the last registered method.").Buffer());
						CHECK_ERROR(matchedCount == 1, (WString::Unmanaged(macroName) + L"#The named parameter is ambiguous on the last registered method.").Buffer());
						return matchedParameter;
					}
				}
			}

#endif

/***********************************************************************
Type
***********************************************************************/

#define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{
#define END_TYPE_INFO_NAMESPACE }}}
#define ADD_TYPE_INFO(TYPENAME)\
			{\
				auto type = Ptr(new CustomTypeDescriptorSelector<TYPENAME>::CustomTypeDescriptorImpl());\
				manager->SetTypeDescriptor(TypeInfo<TYPENAME>::content.typeName, type);\
			}

/***********************************************************************
InterfaceProxy
***********************************************************************/

#define INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
			static INTERFACE* Create(Ptr<IValueInterfaceProxy> proxy)\
			{\
				auto obj = new ValueInterfaceProxy<INTERFACE>();\
				obj->SetProxy(proxy);\
				return obj;\
			}\

#define INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
			static Ptr<INTERFACE> Create(Ptr<IValueInterfaceProxy> proxy)\
			{\
				auto obj = Ptr(new ValueInterfaceProxy<INTERFACE>());\
				obj->SetProxy(proxy);\
				return obj;\
			}\

#define BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
			template<>\
			class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE>\
			{\
				typedef INTERFACE _interface_proxy_InterfaceType;\
			public:\

#define BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(INTERFACE)\
			BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
			INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\

#define BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(INTERFACE)\
			BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
			INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\

#define BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, ...)\
			template<>\
			class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE, __VA_ARGS__>\
			{\
				typedef INTERFACE _interface_proxy_InterfaceType;\
			public:\

#define BEGIN_INTERFACE_PROXY_RAWPTR(INTERFACE, ...)\
			BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
			INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\

#define BEGIN_INTERFACE_PROXY_SHAREDPTR(INTERFACE, ...)\
			BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
			INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\

#define END_INTERFACE_PROXY(INTERFACE)\
			};

/***********************************************************************
InterfaceProxy::Invoke
***********************************************************************/

			template<typename TClass, typename TReturn, typename ...TArgument>
			auto MethodTypeTrait(TArgument...)->TReturn(TClass::*)(TArgument...)
			{
				return nullptr;
			}

#define PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
			static ITypeDescriptor* _interface_proxy_typeDescriptor = nullptr;\
			static IMethodInfo* _interface_proxy_methodInfo = nullptr;\
			if (_interface_proxy_typeDescriptor != static_cast<DescriptableObject*>(this)->GetTypeDescriptor())\
			{\
				_interface_proxy_typeDescriptor = static_cast<DescriptableObject*>(this)->GetTypeDescriptor();\
				CHECK_ERROR(_interface_proxy_typeDescriptor != nullptr, L"Internal error: The type of this interface has not been registered.");\
				auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(_interface_proxy_typeDescriptor);\
				CHECK_ERROR(impl != nullptr, L"Internal error: BEGIN_INTERFACE_PROXY is the only correct way to register an interface with a proxy.");\
				auto _interface_proxy_method\
					= (decltype(MethodTypeTrait<_interface_proxy_InterfaceType, decltype(METHODNAME(__VA_ARGS__))>(__VA_ARGS__)))\
					&_interface_proxy_InterfaceType::METHODNAME;\
				MethodPointerBinaryDataRetriver<decltype(_interface_proxy_method)> binaryData(_interface_proxy_method);\
				_interface_proxy_methodInfo = impl->GetIndexedMethodInfo(binaryData.GetBinaryData());\
			}\

#define INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
			PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
			proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))

#define INVOKE_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
			PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
			proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())

#define INVOKEGET_INTERFACE_PROXY(METHODNAME, ...)\
			PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
			return UnboxParameter<decltype(METHODNAME(__VA_ARGS__))>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))).Ref()

#define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
			PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
			return UnboxParameter<decltype(METHODNAME())>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())).Ref()

/***********************************************************************
Enum
***********************************************************************/

#define BEGIN_ENUM_ITEM_FLAG(TYPENAME, TDFLAGS)\
			template<>\
			struct CustomTypeDescriptorSelector<TYPENAME>\
			{\
			public:\
				class CustomTypeDescriptorImpl : public EnumTypeDescriptor<TYPENAME, TDFLAGS>\
				{\
					typedef TYPENAME EnumType;\
				public:\
					void LoadInternal()override\
					{\
						EnumTypeDescriptor<TYPENAME, TDFLAGS>::LoadInternal();\

#define BEGIN_ENUM_ITEM(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::NormalEnum)
#define BEGIN_ENUM_ITEM_MERGABLE(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::FlagEnum)

#define END_ENUM_ITEM(TYPENAME)\
					}\
				};\
			};

#define ENUM_ITEM_NAMESPACE(TYPENAME) typedef TYPENAME EnumItemNamespace;
#define ENUM_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, ITEMNAME);
#define ENUM_NAMESPACE_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumItemNamespace::ITEMNAME);
#define ENUM_CLASS_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumType::ITEMNAME);

/***********************************************************************
Struct
***********************************************************************/

#define BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TDFLAGS)\
			template<>\
			struct CustomTypeDescriptorSelector<TYPENAME>\
			{\
			public:\
				class CustomTypeDescriptorImpl : public StructTypeDescriptor<TYPENAME, TDFLAGS>\
				{\
					typedef TYPENAME StructType;\
				protected:\
					void LoadInternal()override\
					{

#define BEGIN_STRUCT_MEMBER(TYPENAME)\
			BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TypeDescriptorFlags::Struct)

#define END_STRUCT_MEMBER(TYPENAME)\
					}\
				};\
			};

#define STRUCT_MEMBER(FIELDNAME)\
	AddField(Ptr(new StructFieldInfo<decltype(((StructType*)0)->FIELDNAME)>(this, &StructType::FIELDNAME, L ## #FIELDNAME)));

/***********************************************************************
Class
***********************************************************************/

#define BEGIN_CLASS_MEMBER(TYPENAME)\
			template<>\
			struct CustomTypeDescriptorSelector<TYPENAME>\
			{\
			public:\
				class CustomTypeDescriptorImpl : public TypeDescriptorImpl\
				{\
					typedef TYPENAME ClassType;\
					static const TypeDescriptorFlags		TDFlags = TypeDescriptorFlags::Class;\
				public:\
					CustomTypeDescriptorImpl()\
						:TypeDescriptorImpl(TDFlags, &TypeInfo<TYPENAME>::content)\
					{\
						Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
					}\
					~CustomTypeDescriptorImpl()\
					{\
						Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
					}\
				protected:\
					bool IsAggregatable()override\
					{\
						return std::is_convertible_v<TYPENAME*, AggregatableDescription<TYPENAME>*>;\
					}\
					void LoadInternal()override\
					{

#define CLASS_MEMBER_BASE(TYPENAME)\
			AddBaseType(description::GetTypeDescriptor<TYPENAME>());

#define END_CLASS_MEMBER(TYPENAME)\
						if (GetBaseTypeDescriptorCount() == 0) CLASS_MEMBER_BASE(DescriptableObject)\
					}\
				};\
			};

#ifndef VCZH_DEBUG_NO_REFLECTION

#define ATTRIBUTE_TYPE(TYPE, ...)\
			RegisterAttribute(nullptr, detail::attribute_macro::MakeAttributeInfo<TYPE>(__VA_ARGS__));

#define ATTRIBUTE_MEMBER(TYPE, ...)\
			{\
				auto attributeTargetMember = GetLastRegisteredMember();\
				CHECK_ERROR(attributeTargetMember != nullptr, L"ATTRIBUTE_MEMBER#This macro must appear after a reflected member.");\
				RegisterAttribute(attributeTargetMember, detail::attribute_macro::MakeAttributeInfo<TYPE>(__VA_ARGS__));\
			}

#define ATTRIBUTE_PARAMETER(PARAMETER_NAME, TYPE, ...)\
			{\
				auto attributeTargetMethod = dynamic_cast<IMethodInfo*>(GetLastRegisteredMember());\
				CHECK_ERROR(attributeTargetMethod != nullptr, L"ATTRIBUTE_PARAMETER#This macro must appear after a reflected method or constructor.");\
				auto attributeTargetParameter = detail::attribute_macro::FindParameter(attributeTargetMethod, WString::Unmanaged(PARAMETER_NAME), L"ATTRIBUTE_PARAMETER");\
				RegisterAttribute(attributeTargetParameter, detail::attribute_macro::MakeAttributeInfo<TYPE>(__VA_ARGS__));\
			}

#endif

/***********************************************************************
Interface
***********************************************************************/

#define BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TDFLAGS)\
			template<>\
			struct CustomTypeDescriptorSelector<TYPENAME>\
			{\
			public:\
				class CustomTypeDescriptorImpl : public TypeDescriptorImpl, public MethodPointerBinaryData::IIndexer\
				{\
					typedef TYPENAME						ClassType;\
					static const TypeDescriptorFlags		TDFlags = TDFLAGS;\
					MethodPointerBinaryData::MethodMap		methodsForProxy;\
				public:\
					CustomTypeDescriptorImpl()\
						:TypeDescriptorImpl(TDFLAGS, &TypeInfo<TYPENAME>::content)\
					{\
						Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
					}\
					~CustomTypeDescriptorImpl()\
					{\
						Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
					}\
					void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo)override\
					{\
						methodsForProxy.Add(data, methodInfo);\
					}\
					IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data)override\
					{\
						Load();\
						return methodsForProxy[data];\
					}\
				protected:\
					void LoadInternal()override\
					{

#define BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
			BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TypeDescriptorFlags::Interface)

#define BEGIN_INTERFACE_MEMBER(TYPENAME)\
	BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
	CLASS_MEMBER_EXTERNALCTOR(decltype(ValueInterfaceProxy<TYPENAME>::Create(nullptr))(Ptr<IValueInterfaceProxy>), { L"proxy" }, vl::reflection::description::ValueInterfaceProxy<TYPENAME>::Create)

#define END_INTERFACE_MEMBER(TYPENAME)\
						if (GetBaseTypeDescriptorCount() == 0 && TDFlags == TypeDescriptorFlags::Interface) CLASS_MEMBER_BASE(IDescriptable)\
					}\
				};\
			};

/***********************************************************************
Field
***********************************************************************/

#define CLASS_MEMBER_FIELD(FIELDNAME)\
			AddProperty(\
				Ptr(new CustomFieldInfoImpl<\
					ClassType,\
					decltype(((ClassType*)0)->FIELDNAME)\
					>(this, L ## #FIELDNAME, &ClassType::FIELDNAME)\
				));

/***********************************************************************
Constructor
***********************************************************************/

#define NO_PARAMETER {L""}
#define PROTECT_PARAMETERS(...) __VA_ARGS__

#define CLASS_MEMBER_CONSTRUCTOR(FUNCTIONTYPE, PARAMETERNAMES)\
			{\
				const wchar_t* parameterNames[]=PARAMETERNAMES;\
				AddConstructor(Ptr(new CustomConstructorInfoImpl<FUNCTIONTYPE>(parameterNames)));\
			}

#define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
			{\
				const wchar_t* parameterNames[]=PARAMETERNAMES;\
				AddConstructor(\
					Ptr(new CustomStaticMethodInfoImpl<FUNCTIONTYPE>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
					);\
			}

#define CLASS_MEMBER_EXTERNALCTOR(FUNCTIONTYPE, PARAMETERNAMES, SOURCE)\
			CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PROTECT_PARAMETERS(PARAMETERNAMES), (FUNCTIONNAME_AddPointer<FUNCTIONTYPE>)&::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")

/***********************************************************************
Method
***********************************************************************/

#define CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
			{\
				const wchar_t* parameterNames[]=PARAMETERNAMES;\
				AddMethod(\
					L ## #FUNCTIONNAME,\
					Ptr(new CustomExternalMethodInfoImpl<\
						ClassType,\
						vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
						>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
					);\
			}

#define CLASS_MEMBER_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
			CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($This, $Arguments)", L"::vl::Func<$Func>($This, &::" L ## #SOURCE L")")

#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, INVOKETEMPLATE, CLOSURETEMPLATE)\
			{\
				const wchar_t* parameterNames[]=PARAMETERNAMES;\
				auto methodInfo = Ptr(new CustomMethodInfoImpl<\
						ClassType,\
						vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
						>\
					(parameterNames, (FUNCTIONTYPE)&ClassType::FUNCTIONNAME, INVOKETEMPLATE, CLOSURETEMPLATE));\
				AddMethod(\
					L ## #EXPECTEDNAME,\
					methodInfo\
					);\
				MethodPointerBinaryDataRetriver<FUNCTIONTYPE> binaryDataRetriver(&ClassType::FUNCTIONNAME);\
				MethodPointerBinaryDataRecorder<ClassType, TDFlags>::RecordMethod(binaryDataRetriver.GetBinaryData(), this, methodInfo.Obj());\
			}

#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
			CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, L"$This->" L ## #FUNCTIONNAME L"($Arguments)", L"::vl::Func<$Func>($This, &$Type::" L ## #FUNCTIONNAME L")")

#define CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
			CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(FUNCTIONNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, nullptr, nullptr)

#define CLASS_MEMBER_METHOD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES)\
			CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))

#define CLASS_MEMBER_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
			CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))

/***********************************************************************
Static Method
***********************************************************************/

#define CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
			{\
				const wchar_t* parameterNames[]=PARAMETERNAMES;\
				AddMethod(\
					L ## #FUNCTIONNAME,\
					Ptr(new CustomStaticMethodInfoImpl<\
						std::remove_pointer_t<FUNCTIONTYPE>\
						>(parameterNames, (FUNCTIONTYPE)SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
					);\
			}

#define CLASS_MEMBER_STATIC_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
			CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")

#define CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
			CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &ClassType::FUNCTIONNAME, nullptr, nullptr)

#define CLASS_MEMBER_STATIC_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
			CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))

/***********************************************************************
Event
***********************************************************************/

#define CLASS_MEMBER_EVENT(EVENTNAME)\
			AddEvent(\
				Ptr(new CustomEventInfoImpl<\
					ClassType,\
					CustomEventFunctionTypeRetriver<decltype(&ClassType::EVENTNAME)>::Type\
					>(this, L ## #EVENTNAME, &ClassType::EVENTNAME))\
				);

/***********************************************************************
Property
***********************************************************************/

#define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\
			AddProperty(\
				Ptr(new PropertyInfoImpl(\
					this,\
					L ## #PROPERTYNAME,\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
					nullptr,\
					nullptr\
					))\
				);

#define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\
			AddProperty(\
				Ptr(new PropertyInfoImpl(\
					this,\
					L ## #PROPERTYNAME,\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
					nullptr\
					))\
				);

#define CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, GETTER, SETTER, EVENT)\
			AddProperty(\
				Ptr(new PropertyInfoImpl(\
					this,\
					L ## #PROPERTYNAME,\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
					dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
					))\
				);

#define CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, GETTER, EVENT)\
			AddProperty(\
				Ptr(new PropertyInfoImpl(\
					this,\
					L ## #PROPERTYNAME,\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
					nullptr,\
					dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
					))\
				);

#define CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE(PROPERTYNAME, GETTER, SETTER, REFERENCETEMPLATE)\
			AddProperty(\
				Ptr(new PropertyInfoImpl_StaticCpp(\
					this,\
					L ## #PROPERTYNAME,\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
					dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
					nullptr,\
					WString::Unmanaged(REFERENCETEMPLATE)\
					))\
				);

#define CLASS_MEMBER_PROPERTY_READONLY_FAST(PROPERTYNAME)\
			CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
			CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, Get##PROPERTYNAME)\

#define CLASS_MEMBER_PROPERTY_FAST(PROPERTYNAME)\
			CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
			CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
			CLASS_MEMBER_PROPERTY(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME)\

#define CLASS_MEMBER_PROPERTY_EVENT_FAST(PROPERTYNAME, EVENTNAME)\
			CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
			CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
			CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME, EVENTNAME)\

#define CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(PROPERTYNAME, EVENTNAME)\
			CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
			CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, Get##PROPERTYNAME, EVENTNAME)\

		}
	}
}

#endif
#endif


/***********************************************************************
.\REFLECTION\REFLECTION.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/

#ifndef VCZH_REFLECTION_REFLECTION_REFLECTION
#define VCZH_REFLECTION_REFLECTION_REFLECTION


namespace vl
{
	namespace reflection
	{
		namespace description
		{

/***********************************************************************
Predefined Types
***********************************************************************/

#define REFLECTION_PREDEFINED_PRIMITIVE_TYPES(F)\
			F(vuint8_t)		\
			F(vuint16_t)	\
			F(vuint32_t)	\
			F(vuint64_t)	\
			F(vint8_t)		\
			F(vint16_t)		\
			F(vint32_t)		\
			F(vint64_t)		\
			F(float)		\
			F(double)		\
			F(bool)			\
			F(wchar_t)		\
			F(WString)		\
			F(Locale)		\

#define REFLECTION_PREDEFINED_SERIALIZABLE_TYPES(F)\
			REFLECTION_PREDEFINED_PRIMITIVE_TYPES(F)	\
			F(DateTime)									\

#ifndef VCZH_DEBUG_NO_REFLECTION

#define REFLECTION_PREDEFINED_COMPLEX_TYPES(F, VOID_TYPE)\
			F(VOID_TYPE)					\
			F(VoidValue)					\
			F(IDescriptable)				\
			F(DescriptableObject)			\
			F(DateTime)						\
			F(IValueEnumerator)				\
			F(IValueEnumerable)				\
			F(IValueReadonlyList)			\
			F(IValueArray)					\
			F(IValueList)					\
			F(IValueObservableList)			\
			F(IValueReadonlyDictionary)		\
			F(IValueDictionary)				\
			F(IValueInterfaceProxy)			\
			F(IValueFunctionProxy)			\
			F(IValueSubscription)			\
			F(IValueCallStack)				\
			F(IValueException)				\
			F(IBoxedValue)					\
			F(IBoxedValue::CompareResult)	\
			F(IValueType)					\
			F(IEnumType)					\
			F(ISerializableType)			\
			F(ITypeInfo)					\
			F(ITypeInfo::Decorator)			\
			F(IAttributeInfo)				\
			F(IAttributeBag)				\
			F(IMemberInfo)					\
			F(IEventHandler)				\
			F(IEventInfo)					\
			F(IPropertyInfo)				\
			F(IParameterInfo)				\
			F(IMethodInfo)					\
			F(IMethodGroupInfo)				\
			F(TypeDescriptorFlags)			\
			F(ITypeDescriptor)				\

			DECL_TYPE_INFO(Value)
			REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DECL_TYPE_INFO)
			REFLECTION_PREDEFINED_COMPLEX_TYPES(DECL_TYPE_INFO, void)

#endif

#undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER

/***********************************************************************
Interface Implementation Proxy (Implement)
***********************************************************************/

#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA

#pragma warning(push)
#pragma warning(disable:4250)
			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerator)
				Value GetCurrent()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCurrent);
				}

				vint GetIndex()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetIndex);
				}

				bool Next()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(Next);
				}
			END_INTERFACE_PROXY(IValueEnumerator)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerable)
				Ptr<IValueEnumerator> CreateEnumerator()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(CreateEnumerator);
				}
			END_INTERFACE_PROXY(IValueEnumerable)

			BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueReadonlyList, IValueEnumerable)
				vint GetCount()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
				}

				Value Get(vint index)override
				{
					INVOKEGET_INTERFACE_PROXY(Get, index);
				}

				bool Contains(const Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Contains, value);
				}

				vint IndexOf(const Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(IndexOf, value);
				}
			END_INTERFACE_PROXY(IValueReadonlyList)

			BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueArray, IValueReadonlyList)
				void Set(vint index, const Value& value)override
				{
					INVOKE_INTERFACE_PROXY(Set, index, value);
				}

				void Resize(vint size)override
				{
					INVOKE_INTERFACE_PROXY(Resize, size);
				}
			END_INTERFACE_PROXY(IValueList)

			BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueList, IValueReadonlyList)
				void Set(vint index, const Value& value)override
				{
					INVOKE_INTERFACE_PROXY(Set, index, value);
				}

				vint Add(const Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Add, value);
				}

				vint Insert(vint index, const Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Insert, index, value);
				}

				bool Remove(const Value& value)override
				{
					INVOKEGET_INTERFACE_PROXY(Remove, value);
				}

				bool RemoveAt(vint index)override
				{
					INVOKEGET_INTERFACE_PROXY(RemoveAt, index);
				}

				void Clear()override
				{
					INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
				}
			END_INTERFACE_PROXY(IValueList)

			BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueObservableList, IValueList)
			END_INTERFACE_PROXY(IValueObservableList)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueReadonlyDictionary)
				Ptr<IValueReadonlyList> GetKeys()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetKeys);
				}

				Ptr<IValueReadonlyList> GetValues()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetValues);
				}

				vint GetCount()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
				}

				Value Get(const Value& key)override
				{
					INVOKEGET_INTERFACE_PROXY(Get, key);
				}
			END_INTERFACE_PROXY(IValueReadonlyDictionary)

			BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueDictionary, IValueReadonlyDictionary)
				void Set(const Value& key, const Value& value)override
				{
					INVOKE_INTERFACE_PROXY(Set, key, value);
				}

				bool Remove(const Value& key)override
				{
					INVOKEGET_INTERFACE_PROXY(Remove, key);
				}

				void Clear()override
				{
					INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
				}
			END_INTERFACE_PROXY(IValueDictionary)

			BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueSubscription)
				bool Open()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(Open);
				}

				bool Update()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(Update);
				}

				bool Close()override
				{
					INVOKEGET_INTERFACE_PROXY_NOPARAMS(Close);
				}
			END_INTERFACE_PROXY(IValueSubscription)

#pragma warning(pop)

#endif

/***********************************************************************
Helper Functions
***********************************************************************/

			extern vint										ITypeDescriptor_GetTypeDescriptorCount();
			extern ITypeDescriptor*							ITypeDescriptor_GetTypeDescriptor(vint index);
			extern ITypeDescriptor*							ITypeDescriptor_GetTypeDescriptor(const WString& name);
			extern ITypeDescriptor*							ITypeDescriptor_GetTypeDescriptor(const Value& value);

/***********************************************************************
LoadPredefinedTypes
***********************************************************************/

			/// <summary>Register all reflectable types in <b>VlppReflection</b>.</summary>
			/// <returns>Returns true if this operation succeeded.</returns>
			extern bool										LoadPredefinedTypes();
		}
	}
}

#endif

