Files
GacUI/Import/VlppReflection.h
2021-10-27 01:31:04 -07:00

7454 lines
253 KiB
C++

/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "VlppOS.h"
#include "Vlpp.h"
#include "VlppRegex.h"
/***********************************************************************
.\GUITYPEDESCRIPTOR.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTOR
#define VCZH_REFLECTION_GUITYPEDESCRIPTOR
#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
{
/***********************************************************************
Attribute
***********************************************************************/
namespace description
{
class ITypeDescriptor;
class ITypeInfo;
class IEventHandler;
class IEventInfo;
class IPropertyInfo;
class IParameterInfo;
class IMethodInfo;
class IMethodGroupInfo;
class IValueFunctionProxy;
class IValueInterfaceProxy;
class IValueSubscription;
class IValueEnumerable;
class IValueEnumerator;
class IValueReadonlyList;
class IValueList;
class IValueObservableList;
class IValueReadonlyDictionary;
class IValueDictionary;
class IValueCallStack;
class IValueException;
template<typename T>
struct TypedValueSerializerProvider
{
};
}
/// <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 = MakePtr<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:
volatile 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();
#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)
///
/// 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
};
/// <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>
{
};
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
template<typename T>
description::ITypeDescriptor* Description<T>::associatedTypeDescriptor=0;
#endif
/// <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 volatile 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(volatile vint* counter, void* reference)
{
reflection::DescriptableObject* obj=(T*)reference;
obj->Dispose(false);
}
};
namespace reflection
{
namespace description
{
/***********************************************************************
Value
***********************************************************************/
class IBoxedValue : public virtual IDescriptable, public Description<IBoxedValue>
{
public:
enum CompareResult
{
Smaller,
Greater,
Equal,
NotComparable,
};
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);
vint Compare(const Value& a, const Value& b)const;
public:
/// <summary>Create a null value.</summary>
Value();
Value(const Value& value);
Value& operator=(const Value& value);
bool operator==(const Value& value)const { return Compare(*this, value) == 0; }
bool operator!=(const Value& value)const { return Compare(*this, value) != 0; }
bool operator<(const Value& value)const { return Compare(*this, value)<0; }
bool operator<=(const Value& value)const { return Compare(*this, value) <= 0; }
bool operator>(const Value& value)const { return Compare(*this, value)>0; }
bool operator>=(const Value& value)const { return Compare(*this, value) >= 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<CallbackType>(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<CallbackType>(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();
};
/***********************************************************************
ValueType
***********************************************************************/
class IValueType : public virtual IDescriptable, public Description<IValueType>
{
public:
template<typename T>
class TypedBox : public IBoxedValue
{
private:
template<typename U = T>
static CompareResult ComparePrimitiveInternal(const U& a, const U& b, std::enable_if_t<sizeof(decltype(&TypedValueSerializerProvider<U>::Compare)) >= 0, vint>)
{
return TypedValueSerializerProvider<U>::Compare(a, b);
}
template<typename U = T>
static CompareResult ComparePrimitiveInternal(const U& a, const U& b, double)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdynamic-class-memaccess"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
auto result = memcmp(&a, &b, sizeof(U));
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
if (result < 0) return IBoxedValue::Smaller;
if (result > 0) return IBoxedValue::Greater;
return IBoxedValue::Equal;
}
public:
T value;
TypedBox()
:value{}
{
}
TypedBox(const T& _value)
:value(_value)
{
}
Ptr<IBoxedValue> Copy()override
{
return new TypedBox<T>(value);
}
CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue)override
{
if (auto typedBox = boxedValue.Cast<TypedBox<T>>())
{
return ComparePrimitiveInternal(value, typedBox->value, (vint)0);
}
else
{
return IBoxedValue::NotComparable;
}
}
};
virtual Value CreateDefault() = 0;
virtual IBoxedValue::CompareResult Compare(const Value& a, const Value& b) = 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 IMemberInfo : public virtual IDescriptable, 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<IValueList> 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 IDescriptable, 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
***********************************************************************/
class TypeDescriptorException abstract : public Exception
{
public:
TypeDescriptorException(const WString& message)
:Exception(message)
{
}
};
class ValueNotDisposableException : public TypeDescriptorException
{
public:
ValueNotDisposableException()
:TypeDescriptorException(L"Cannot dispose an object whose reference counter is not 0.")
{
}
};
#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, 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
/***********************************************************************
.\GUITYPEDESCRIPTORPREDEFINED.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORPREDEFINED
#define VCZH_REFLECTION_GUITYPEDESCRIPTORPREDEFINED
#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 MakePtr<MyClass>(i);
/// });
///
/// Value boxed = BoxParameter<LazyList<Ptr<MyClass>>>(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>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"/>
/// </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 readonly
/// <see cref="collections::Array`2"/> or
/// <see cref="collections::List`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 MakePtr<MyClass>(i);
/// })
/// );
///
/// Value boxed = BoxParameter<List<Ptr<MyClass>>>(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 MakePtr<MyClass>(i);
/// })
/// );
///
/// Value boxed = BoxValue(cs.GetWrapper());
/// 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<CallbackType>(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>
/// The reflectable version of <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, MakePtr<MyClass>(i * i) };
/// })
/// );
///
/// Value boxed = BoxParameter<Dictionary<vint, Ptr<MyClass>>>(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<IValueList> 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<IValueList> 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 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
/***********************************************************************
.\GUITYPEDESCRIPTORBUILDER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER
namespace vl
{
namespace collections
{
template<typename T>
class ObservableList;
}
namespace reflection
{
namespace description
{
#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);
};
#endif
#ifndef VCZH_DEBUG_NO_REFLECTION
/***********************************************************************
SerializableTypeDescriptor
***********************************************************************/
class TypeDescriptorImplBase : public Object, public ITypeDescriptor, private ITypeDescriptor::ICpp
{
private:
TypeDescriptorFlags typeDescriptorFlags;
const TypeInfoContent* typeInfoContent;
WString typeName;
WString cppFullTypeName;
const WString& GetFullName()override;
protected:
const TypeInfoContent* GetTypeInfoContentInternal();
public:
TypeDescriptorImplBase(TypeDescriptorFlags _typeDescriptorFlags, const TypeInfoContent* _typeInfoContent);
~TypeDescriptorImplBase();
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();
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 Object, public 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 Object, public 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();
ITypeDescriptor* GetOwnerTypeDescriptor()override;
const WString& GetName()override;
vint GetMethodCount()override;
IMethodInfo* GetMethod(vint index)override;
bool AddMethod(Ptr<IMethodInfo> _method);
};
/***********************************************************************
EventInfoImpl
***********************************************************************/
class EventInfoImpl : public Object, public 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<IValueList> 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<IValueList> arguments)override;
};
/***********************************************************************
TypeDescriptorImpl
***********************************************************************/
class PropertyInfoImpl : public Object, public 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 Object, public 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();
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
/***********************************************************************
TypeFlagTester
***********************************************************************/
enum class TypeFlags
{
NonGenericType =0,
FunctionType =1<<0,
EnumerableType =1<<1,
ReadonlyListType =1<<2,
ListType =1<<3,
ObservableListType =1<<4,
ReadonlyDictionaryType =1<<5,
DictionaryType =1<<6,
};
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 {}; }
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::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::ReadonlyListType:TypeFlags::NonGenericType;
};
template<typename TDerived>
struct TypeFlagTester<TDerived, TypeFlags::ListType>
{
template<typename T>
static void* Inherit(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::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|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::EnumerableType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::EnumerableType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::ListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ObservableListType|(vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result = TypeFlags::ObservableListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ReadonlyListType)>
{
static const TypeFlags Result=TypeFlags::ReadonlyListType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ListType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::DictionaryType|(vint)TypeFlags::ReadonlyDictionaryType)>
{
static const TypeFlags Result=TypeFlags::DictionaryType;
};
template<typename T>
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ReadonlyDictionaryType)>
{
static const TypeFlags Result=TypeFlags::ReadonlyDictionaryType;
};
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::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;
};
/***********************************************************************
TypeInfoRetriver
***********************************************************************/
template<typename T, TypeFlags Flag>
struct DetailTypeInfoRetriver
{
static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor;
typedef void Type;
typedef void TempValueType;
typedef void ResultReferenceType;
typedef void ResultNonReferenceType;
};
template<typename T>
struct TypeInfoRetriver
{
static const TypeFlags TypeFlag = TypeFlagSelector<T>::Result;
static const TypeInfoHint Hint = TypeHintTester<T>::Result;
static const ITypeInfo::Decorator Decorator = DetailTypeInfoRetriver<T, TypeFlag>::Decorator;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::Type Type;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::TempValueType TempValueType;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::ResultReferenceType ResultReferenceType;
typedef typename DetailTypeInfoRetriver<T, TypeFlag>::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo()
{
return DetailTypeInfoRetriver<std::remove_cvref_t<T>, TypeFlag>::CreateTypeInfo(Hint);
}
#endif
};
/***********************************************************************
TypeInfoRetriver Helper Functions (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=0)
{
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=0, const WString& valueName=L"value")
{
using Type = std::remove_cvref_t<T>;
return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::UnboxValue(value, typeDescriptor, valueName);
}
/***********************************************************************
TypeInfoRetriver Helper Functions (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(typename TypeInfoRetriver<T>::ResultReferenceType object, ITypeDescriptor* typeDescriptor=0)
{
return ParameterAccessor<typename TypeInfoRetriver<T>::ResultNonReferenceType, TypeInfoRetriver<T>::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>
/// <param name="value">The value to unbox.</param>
/// <param name="result">The unboxed object.</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>
void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor=0, const WString& valueName=L"value")
{
ParameterAccessor<T, TypeInfoRetriver<T>::TypeFlag>::UnboxParameter(value, result, typeDescriptor, valueName);
}
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
/***********************************************************************
Value_xs
***********************************************************************/
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<T>(value);
return *this;
}
template<typename T>
Value_xs& operator,(const T& value)
{
arguments.Resize(arguments.Count() + 1);
arguments[arguments.Count() - 1] = BoxParameter<const T>(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;
}
};
/***********************************************************************
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<TField>(object->*fieldRef, GetReturn()->GetTypeDescriptor());
}
return Value();
}
void SetValueInternal(Value& thisObject, const Value& newValue)override
{
TClass* object=UnboxValue<TClass*>(thisObject);
if(object)
{
UnboxParameter<TField>(newValue, object->*fieldRef, GetReturn()->GetTypeDescriptor(), L"newValue");
}
}
public:
CustomFieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, TField TClass::* _fieldRef)
:FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
, fieldRef(_fieldRef)
{
}
IPropertyInfo::ICpp* GetCpp()override
{
return nullptr;
}
};
#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());
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
auto va = UnboxValue<T>(a);
auto vb = UnboxValue<T>(b);
return TypedValueSerializerProvider<T>::Compare(va, vb);
}
};
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 = new SerializableValueType<T>();
this->serializableType = 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));
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
auto ea = static_cast<vuint64_t>(UnboxValue<T>(a));
auto eb = static_cast<vuint64_t>(UnboxValue<T>(b));
if (ea < eb) return IBoxedValue::Smaller;
if (ea > eb)return IBoxedValue::Greater;
return IBoxedValue::Equal;
}
};
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 = new TEnumType;
this->valueType = 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{});
}
IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override
{
return IBoxedValue::NotComparable;
}
};
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:
StructTypeDescriptor()
{
this->valueType = 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
/***********************************************************************
.\GUITYPEDESCRIPTORBUILDER_CONTAINER.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
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<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 T>
class ValueEnumeratorWrapper : public Object, public virtual IValueEnumerator
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
T wrapperPointer;
public:
ValueEnumeratorWrapper(const T& _wrapperPointer)
:wrapperPointer(_wrapperPointer)
{
}
Value GetCurrent()override
{
return BoxValue<ElementType>(wrapperPointer->Current());
}
vint GetIndex()override
{
return wrapperPointer->Index();
}
bool Next()override
{
return wrapperPointer->Next();
}
};
template<typename T>
class ValueEnumerableWrapper : public Object, public virtual IValueEnumerable
{
protected:
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
T wrapperPointer;
public:
ValueEnumerableWrapper(const T& _wrapperPointer)
:wrapperPointer(_wrapperPointer)
{
}
Ptr<IValueEnumerator> CreateEnumerator()override
{
return new ValueEnumeratorWrapper<Ptr<collections::IEnumerator<ElementType>>>(wrapperPointer->CreateEnumerator());
}
};
#define WRAPPER_POINTER this->wrapperPointer
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
{
return WRAPPER_POINTER->Count();
}
Value Get(vint index)override
{
return BoxValue<ElementType>(WRAPPER_POINTER->Get(index));
}
bool Contains(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Contains(item);
}
vint IndexOf(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->IndexOf(item);
}
};
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
{
ElementType item=UnboxValue<ElementType>(value);
WRAPPER_POINTER->Set(index, item);
}
vint Add(const Value& value)override
{
ElementType item=UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Add(item);
}
vint Insert(vint index, const Value& value)override
{
ElementType item=UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Insert(index, item);
}
bool Remove(const Value& value)override
{
ElementKeyType item=UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Remove(item);
}
bool RemoveAt(vint index)override
{
return WRAPPER_POINTER->RemoveAt(index);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
template<typename T, typename K>
class ValueListWrapper<collections::Array<T, K>*> : public ValueReadonlyListWrapper<collections::Array<T, K>*>, public virtual IValueList
{
protected:
typedef collections::Array<T, K> ContainerType;
typedef T ElementType;
typedef K ElementKeyType;
public:
ValueListWrapper(collections::Array<T, K>* _wrapperPointer)
:ValueReadonlyListWrapper<collections::Array<T, K>*>(_wrapperPointer)
{
}
void Set(vint index, const Value& value)override
{
ElementType item = UnboxValue<ElementType>(value);
WRAPPER_POINTER->Set(index, item);
}
vint Add(const Value& value)override
{
throw Exception(L"Array doesn't have Add method.");
}
vint Insert(vint index, const Value& value)override
{
throw Exception(L"Array doesn't have Insert method.");
}
bool Remove(const Value& value)override
{
throw Exception(L"Array doesn't have Remove method.");
}
bool RemoveAt(vint index)override
{
throw Exception(L"Array doesn't have RemoveAt method.");
}
void Clear()override
{
throw Exception(L"Array doesn't have Clear method.");
}
};
template<typename T, typename K>
class ValueListWrapper<collections::SortedList<T, K>*> : public ValueReadonlyListWrapper<collections::SortedList<T, K>*>, public virtual IValueList
{
protected:
typedef collections::SortedList<T, K> ContainerType;
typedef T ElementType;
typedef K ElementKeyType;
public:
ValueListWrapper(collections::SortedList<T, K>* _wrapperPointer)
:ValueReadonlyListWrapper<collections::SortedList<T, K>*>(_wrapperPointer)
{
}
void Set(vint index, const Value& value)override
{
throw Exception(L"SortedList doesn't have Set method.");
}
vint Add(const Value& value)override
{
ElementType item = UnboxValue<ElementType>(value);
return WRAPPER_POINTER->Add(item);
}
vint Insert(vint index, const Value& value)override
{
throw Exception(L"SortedList doesn't have Insert method.");
}
bool Remove(const Value& value)override
{
ElementKeyType item = UnboxValue<ElementKeyType>(value);
return WRAPPER_POINTER->Remove(item);
}
bool RemoveAt(vint index)override
{
return WRAPPER_POINTER->RemoveAt(index);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
template<typename T>
class ValueObservableListWrapper : public ValueListWrapper<T>, public virtual IValueObservableList
{
public:
ValueObservableListWrapper(const T& _wrapperPointer)
:ValueListWrapper<T>(_wrapperPointer)
{
}
};
#undef WRAPPER_POINTER
template<typename T>
class ValueReadonlyDictionaryWrapper : public virtual Object, 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)
{
}
Ptr<IValueReadonlyList> GetKeys()override
{
if(!keys)
{
keys=new ValueReadonlyListWrapper<const KeyContainer*>(&wrapperPointer->Keys());
}
return keys;
}
Ptr<IValueReadonlyList> GetValues()override
{
if(!values)
{
values=new ValueReadonlyListWrapper<const ValueContainer*>(&wrapperPointer->Values());
}
return values;
}
vint GetCount()override
{
return wrapperPointer->Count();
}
Value Get(const Value& key)override
{
KeyKeyType item=UnboxValue<KeyKeyType>(key);
ValueType result=wrapperPointer->Get(item);
return BoxValue<ValueType>(result);
}
};
#define WRAPPER_POINTER ValueReadonlyDictionaryWrapper<T>::wrapperPointer
#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
{
KEY_VALUE_TYPE item=UnboxValue<KEY_VALUE_TYPE>(key);
VALUE_TYPE result=UnboxValue<VALUE_TYPE>(value);
WRAPPER_POINTER->Set(item, result);
}
bool Remove(const Value& key)override
{
KEY_KEY_TYPE item=UnboxValue<KEY_KEY_TYPE>(key);
return WRAPPER_POINTER->Remove(item);
}
void Clear()override
{
WRAPPER_POINTER->Clear();
}
};
#undef WRAPPER_POINTER
#undef KEY_VALUE_TYPE
#undef VALUE_TYPE
#undef KEY_KEY_TYPE
#pragma warning(pop)
/***********************************************************************
DetailTypeInfoRetriver<TContainer>
***********************************************************************/
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::EnumerableType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueEnumerable Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueEnumerable>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueReadonlyList>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueList>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ObservableListType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator;
typedef IValueObservableList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::ElementType ElementType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueObservableList>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<ElementType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyDictionaryType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::KeyContainer KeyContainer;
typedef typename ContainerType::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueReadonlyDictionary>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<KeyType>::CreateTypeInfo());
genericType->AddGenericArgument(TypeInfoRetriver<ValueType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::DictionaryType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef IValueReadonlyList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
typedef typename DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>::Type ContainerType;
typedef typename ContainerType::KeyContainer KeyContainer;
typedef typename ContainerType::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
auto arrayType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueDictionary>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(arrayType);
genericType->AddGenericArgument(TypeInfoRetriver<KeyType>::CreateTypeInfo());
genericType->AddGenericArgument(TypeInfoRetriver<ValueType>::CreateTypeInfo());
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
/***********************************************************************
ParameterAccessor<TContainer>
***********************************************************************/
template<typename T>
struct ParameterAccessor<collections::LazyList<T>, TypeFlags::EnumerableType>
{
static Value BoxParameter(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<Ptr<IValueEnumerable>>(result, td);
}
static void UnboxParameter(const Value& value, collections::LazyList<T>& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename collections::LazyList<T>::ElementType ElementType;
Ptr<IValueEnumerable> listProxy=UnboxValue<Ptr<IValueEnumerable>>(value, typeDescriptor, valueName);
result=GetLazyList<T>(listProxy);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ReadonlyListType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueReadonlyList> result=new ValueReadonlyListWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueReadonlyList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueReadonlyList>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::ElementType ElementType;
Ptr<IValueReadonlyList> listProxy=UnboxValue<Ptr<IValueReadonlyList>>(value, typeDescriptor, valueName);
collections::LazyList<ElementType> lazyList=GetLazyList<ElementType>(listProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ListType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueList> result=new ValueListWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueList>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::ElementType ElementType;
Ptr<IValueList> listProxy=UnboxValue<Ptr<IValueList>>(value, typeDescriptor, valueName);
collections::LazyList<ElementType> lazyList=GetLazyList<ElementType>(listProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<collections::ObservableList<T>, TypeFlags::ObservableListType>
{
static Value BoxParameter(collections::ObservableList<T>& object, ITypeDescriptor* typeDescriptor)
{
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueObservableList>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueObservableList>>(object.GetWrapper(), td);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::ReadonlyDictionaryType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueReadonlyDictionary> result=new ValueReadonlyDictionaryWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueReadonlyDictionary>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueReadonlyDictionary>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::KeyContainer KeyContainer;
typedef typename T::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
Ptr<IValueReadonlyDictionary> dictionaryProxy=UnboxValue<Ptr<IValueReadonlyDictionary>>(value, typeDescriptor, valueName);
collections::LazyList<collections::Pair<KeyType, ValueType>> lazyList=GetLazyList<KeyType, ValueType>(dictionaryProxy);
collections::CopyFrom(result, lazyList);
}
};
template<typename T>
struct ParameterAccessor<T, TypeFlags::DictionaryType>
{
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
{
Ptr<IValueDictionary> result=new ValueDictionaryWrapper<T*>(&object);
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueDictionary>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueDictionary>>(result, td);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef typename T::KeyContainer KeyContainer;
typedef typename T::ValueContainer ValueContainer;
typedef typename KeyContainer::ElementType KeyType;
typedef typename ValueContainer::ElementType ValueType;
Ptr<IValueDictionary> dictionaryProxy=UnboxValue<Ptr<IValueDictionary>>(value, typeDescriptor, valueName);
collections::LazyList<collections::Pair<KeyType, ValueType>> lazyList=GetLazyList<KeyType, ValueType>(dictionaryProxy);
collections::CopyFrom(result, lazyList);
}
};
}
}
namespace collections
{
/// <summary>Base type of observable container which triggers callbacks whenever items are changed.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements. It is recommended to use the default value.</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, typename K = typename KeyType<T>::Type>
class ObservableListBase : public Object, public virtual collections::IEnumerable<T>
{
protected:
collections::List<T, K> 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:
ObservableListBase()
{
}
~ObservableListBase()
{
}
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>
/// <typeparam name="K">Type of the key type of elements. It is recommended to use the default value.</typeparam>
template<typename T>
class ObservableList : public ObservableListBase<T>
{
protected:
Ptr<reflection::description::IValueObservableList> observableList;
void NotifyUpdateInternal(vint start, vint count, vint newCount)override
{
if (observableList)
{
observableList->ItemChanged(start, count, newCount);
}
}
public:
/// <summary>
/// Get the maintained observable list.
/// <see cref="reflection::description::IValueObservableList::ItemChanged"/> of the observable list
/// will be automatically triggered when any changing happens.
/// </summary>
/// <returns>The maintained observable list.</returns>
/// <remarks>
/// <p>
/// <see cref="reflection::description::BoxParameter`1"/>
/// cannot turn any predefined C++ object to an reflectable observable list
/// and keep it binding to the C++ object.
/// When an reflectable observable list is required, ObservableList is strongly recommended.
/// </p>
/// </remarks>
Ptr<reflection::description::IValueObservableList> GetWrapper()
{
if (!observableList)
{
observableList = new reflection::description::ValueObservableListWrapper<ObservableList<T>*>(this);
}
return observableList;
}
};
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
/***********************************************************************
.\GUITYPEDESCRIPTORBUILDER_FUNCTION.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_FUNCTION
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_FUNCTION
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 MakePtr<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;
}
};
/***********************************************************************
DetailTypeInfoRetriver<Func<R(TArgs...)>>
***********************************************************************/
#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;
typedef IValueList Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef typename UpLevelRetriver::ResultReferenceType ResultReferenceType;
typedef typename UpLevelRetriver::ResultNonReferenceType ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
auto functionType = MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<IValueFunctionProxy>(), hint);
auto genericType = MakePtr<GenericTypeInfo>(functionType);
genericType->AddGenericArgument(TypeInfoRetriver<R>::CreateTypeInfo());
internal_helper::GenericArgumentAdder<TypeTuple<TArgs...>>::Add(genericType);
auto type = MakePtr<SharedPtrTypeInfo>(genericType);
return type;
}
#endif
};
template<typename R, typename ...TArgs>
struct DetailTypeInfoRetriver<const Func<R(TArgs...)>, TypeFlags::FunctionType>
: DetailTypeInfoRetriver<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
};
/***********************************************************************
ValueFunctionProxyWrapper<Func<R(TArgs...)>>
***********************************************************************/
template<typename T>
class ValueFunctionProxyWrapper
{
};
namespace internal_helper
{
extern void UnboxSpecifiedParameter(Ptr<IValueList> arguments, vint index);
template<typename T0, typename ...TArgs>
void UnboxSpecifiedParameter(Ptr<IValueList> arguments, vint index, T0& p0, TArgs& ...args)
{
UnboxParameter<typename TypeInfoRetriver<T0>::TempValueType>(arguments->Get(index), p0, 0, itow(index + 1) + L"-th argument");
UnboxSpecifiedParameter(arguments, index + 1, args...);
}
template<typename R, typename ...TArgs>
struct BoxedFunctionInvoker
{
static Value Invoke(const Func<R(TArgs...)>& function, Ptr<IValueList> arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
R result = function(args...);
return BoxParameter<R>(result);
}
};
template<typename ...TArgs>
struct BoxedFunctionInvoker<void, TArgs...>
{
static Value Invoke(const Func<void(TArgs...)>& function, Ptr<IValueList> arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
function(args...);
return Value();
}
};
}
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<IValueList> arguments)override
{
if (!arguments || arguments->GetCount() != sizeof...(TArgs))
{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
throw ArgumentCountMismtatchException();
#else
CHECK_FAIL(L"Argument count mismatch.");
#endif
}
return internal_helper::BoxedFunctionInvoker<R, TArgs...>::Invoke(function, arguments, std::remove_cvref_t<TArgs>()...);
}
};
/***********************************************************************
ParameterAccessor<Func<R(TArgs...)>>
***********************************************************************/
namespace internal_helper
{
extern void AddValueToList(Ptr<IValueList> arguments);
template<typename T0, typename ...TArgs>
void AddValueToList(Ptr<IValueList> arguments, T0&& p0, TArgs&& ...args)
{
arguments->Add(description::BoxParameter<T0>(p0));
AddValueToList(arguments, args...);
}
}
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=new ValueFunctionProxyWrapper<RawFunctionType>(object);
ITypeDescriptor* td = nullptr;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td = Description<IValueFunctionProxy>::GetAssociatedTypeDescriptor();
#endif
return BoxValue<Ptr<IValueFunctionProxy>>(result, td);
}
static void UnboxParameter(const Value& value, Func<R(TArgs...)>& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
typedef R(RawFunctionType)(TArgs...);
typedef ValueFunctionProxyWrapper<RawFunctionType> ProxyType;
Ptr<IValueFunctionProxy> functionProxy=UnboxValue<Ptr<IValueFunctionProxy>>(value, typeDescriptor, valueName);
if(functionProxy)
{
if(Ptr<ProxyType> proxy=functionProxy.Cast<ProxyType>())
{
result=proxy->GetFunction();
}
else
{
result=[functionProxy](TArgs ...args)
{
Ptr<IValueList> arguments = IValueList::Create();
internal_helper::AddValueToList(arguments, std::forward<TArgs>(args)...);
typedef typename TypeInfoRetriver<R>::TempValueType ResultType;
ResultType proxyResult;
description::UnboxParameter<ResultType>(functionProxy->Invoke(arguments), proxyResult);
return proxyResult;
};
}
}
}
};
template<typename R, typename ...TArgs>
struct ParameterAccessor<const Func<R(TArgs...)>, TypeFlags::FunctionType> : ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
{
};
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
/***********************************************************************
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{};
/***********************************************************************
CustomConstructorInfoImpl<R(TArgs...)>
***********************************************************************/
namespace internal_helper
{
extern void UnboxSpecifiedParameter(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, vint index);
template<typename T0, typename ...TArgs>
void UnboxSpecifiedParameter(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, vint index, T0& p0, TArgs& ...args)
{
UnboxParameter<typename TypeInfoRetriver<T0>::TempValueType>(arguments[index], p0, methodInfo->GetParameter(index)->GetType()->GetTypeDescriptor(), itow(index) + L"-th argument");
UnboxSpecifiedParameter(methodInfo, arguments, index + 1, args...);
}
template<typename R, typename ...TArgs>
struct BoxedConstructorInvoker
{
static Value Invoke(MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = new typename TypeInfoRetriver<R>::Type(args...);
return BoxParameter<R>(result);
}
};
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(new ParameterInfoImpl(methodInfo, parameterNames[index], TypeInfoRetriver<T0>::CreateTypeInfo()));
ConstructorArgumentAdder<TypeTuple<TNextArgs...>>::Add(methodInfo, parameterNames, index + 1);
}
};
}
template<typename R, typename ...TArgs>
class CustomConstructorInfoImpl<R(TArgs...)> : public MethodInfoImpl
{
protected:
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
{
return internal_helper::BoxedConstructorInvoker<R, TArgs...>::Invoke(this, arguments, std::remove_cvref_t<TArgs>()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
Func<R(TArgs...)> proxy(
LAMBDA([](TArgs ...args)->R
{
R result = new typename TypeInfoRetriver<R>::Type(args...);
return result;
})
);
return BoxParameter<Func<R(TArgs...)>>(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...)>
CustomStaticMethodInfoImpl<TClass, R(TArgs...)>
***********************************************************************/
namespace internal_helper
{
template<typename TClass, typename R, typename ...TArgs>
struct BoxedMethodInvoker
{
static Value Invoke(TClass* object, R(__thiscall TClass::* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = (object->*method)(args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename TClass, typename ...TArgs>
struct BoxedMethodInvoker<TClass, void, TArgs...>
{
static Value Invoke(TClass* object, void(__thiscall TClass::* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
(object->*method)(args...);
return Value();
}
};
template<typename TClass, typename R, typename ...TArgs>
struct BoxedExternalMethodInvoker
{
static Value Invoke(TClass* object, R(*method)(TClass*, TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = method(object, args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename TClass, typename ...TArgs>
struct BoxedExternalMethodInvoker<TClass, void, TArgs...>
{
static Value Invoke(TClass* object, void(*method)(TClass*, TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
method(object, args...);
return Value();
}
};
}
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 internal_helper::BoxedMethodInvoker<TClass, R, TArgs...>::Invoke(object, method, this, arguments, std::remove_cvref_t<TArgs>()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
Func<R(TArgs...)> proxy(object, method);
return BoxParameter<Func<R(TArgs...)>>(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 internal_helper::BoxedExternalMethodInvoker<TClass, R, TArgs...>::Invoke(object, method, this, arguments, std::remove_cvref_t<TArgs>()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
TClass* object=UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
Func<R(TArgs...)> proxy = Curry(Func<R(TClass*, TArgs...)>(method))(object);
return BoxParameter<Func<R(TArgs...)>>(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...)>
***********************************************************************/
namespace internal_helper
{
template<typename R, typename ...TArgs>
struct BoxedStaticMethodInvoker
{
static Value Invoke(R(* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
R result = method(args...);
return BoxParameter<R>(result, methodInfo->GetReturn()->GetTypeDescriptor());
}
};
template<typename ...TArgs>
struct BoxedStaticMethodInvoker<void, TArgs...>
{
static Value Invoke(void(* method)(TArgs...), MethodInfoImpl* methodInfo, collections::Array<Value>& arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(methodInfo, arguments, 0, args...);
method(args...);
return Value();
}
};
}
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 internal_helper::BoxedStaticMethodInvoker<R, TArgs...>::Invoke(method, this, arguments, std::remove_cvref_t<TArgs>()...);
}
Value CreateFunctionProxyInternal(const Value& thisObject)override
{
Func<R(TArgs...)> proxy(method);
return BoxParameter<Func<R(TArgs...)>>(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);
}
};
/***********************************************************************
CustomEventInfoImpl<void(TArgs...)>
***********************************************************************/
namespace internal_helper
{
template<typename ...TArgs>
struct BoxedEventInvoker
{
static void Invoke(Event<void(TArgs...)>& eventObject, Ptr<IValueList> arguments, std::remove_cvref_t<TArgs>&& ...args)
{
UnboxSpecifiedParameter(arguments, 0, args...);
eventObject(args...);
}
};
}
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();
internal_helper::AddValueToList(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<IValueList> arguments)override
{
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
Event<void(TArgs...)>& eventObject = object->*eventRef;
internal_helper::BoxedEventInvoker<TArgs...>::Invoke(eventObject, arguments, typename std::remove_cvref_t<TArgs>()...);
}
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
/***********************************************************************
.\GUITYPEDESCRIPTORBUILDER_STRUCT.H
***********************************************************************/
/*/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_STRUCT
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_STRUCT
namespace vl
{
namespace reflection
{
namespace description
{
/***********************************************************************
DetailTypeInfoRetriver<TStruct>
***********************************************************************/
template<typename T>
struct DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>
{
static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor;
typedef T Type;
typedef T TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<TypeDescriptorTypeInfo>(GetTypeDescriptor<Type>(), hint);
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<const T, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef T TempValueType;
typedef const T& ResultReferenceType;
typedef const T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<volatile T, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef T TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T*, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=ITypeInfo::RawPtr;
typedef typename UpLevelRetriver::Type Type;
typedef T* TempValueType;
typedef T*& ResultReferenceType;
typedef T* ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<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;
typedef typename UpLevelRetriver::Type Type;
typedef Ptr<T> TempValueType;
typedef Ptr<T>& ResultReferenceType;
typedef Ptr<T> ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<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;
typedef typename UpLevelRetriver::Type Type;
typedef Nullable<T> TempValueType;
typedef Nullable<T>& ResultReferenceType;
typedef Nullable<T> ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return MakePtr<NullableTypeInfo>(TypeInfoRetriver<T>::CreateTypeInfo());
}
#endif
};
template<typename T>
struct DetailTypeInfoRetriver<T&, TypeFlags::NonGenericType>
{
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
typedef typename UpLevelRetriver::Type Type;
typedef typename UpLevelRetriver::TempValueType TempValueType;
typedef T& ResultReferenceType;
typedef T ResultNonReferenceType;
#ifndef VCZH_DEBUG_NO_REFLECTION
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
{
return TypeInfoRetriver<T>::CreateTypeInfo();
}
#endif
};
template<>
struct TypeInfoRetriver<void> : public TypeInfoRetriver<VoidValue>
{
};
/***********************************************************************
ParameterAccessor<TStruct>
***********************************************************************/
template<typename T>
struct ParameterAccessor<T, TypeFlags::NonGenericType>
{
static Value BoxParameter(const T& object, ITypeDescriptor* typeDescriptor)
{
return BoxValue<T>(object, typeDescriptor);
}
static void UnboxParameter(const Value& value, T& result, ITypeDescriptor* typeDescriptor, const WString& valueName)
{
result=UnboxValue<T>(value, typeDescriptor, valueName);
}
};
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 = 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)
{
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
if(!typeDescriptor)
{
typeDescriptor = GetTypeDescriptor<typename TypeInfoRetriver<T>::Type>();
}
#endif
using Type = std::remove_cvref_t<T>;
return Value::From(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<typename TypeInfoRetriver<T>::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
/***********************************************************************
.\GUITYPEDESCRIPTORMACROS.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#define VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#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];
static inline vint Compare(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
{
{
auto result = a.data[0] - b.data[0];
if (result != 0) return result;
}
{
auto result = a.data[1] - b.data[1];
if (result != 0) return result;
}
{
auto result = a.data[2] - b.data[2];
if (result != 0) return result;
}
{
auto result = a.data[3] - b.data[3];
if (result != 0) return result;
}
return 0;
}
#define COMPARE(OPERATOR)\
inline bool operator OPERATOR(const MethodPointerBinaryData& d)const\
{\
return Compare(*this, d) OPERATOR 0;\
}
COMPARE(<)
COMPARE(<=)
COMPARE(>)
COMPARE(>=)
COMPARE(==)
COMPARE(!=)
#undef COMPARE
};
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*;
/***********************************************************************
Type
***********************************************************************/
#define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{
#define END_TYPE_INFO_NAMESPACE }}}
#define ADD_TYPE_INFO(TYPENAME)\
{\
Ptr<ITypeDescriptor> type=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 = 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 UnboxValue<decltype(METHODNAME(__VA_ARGS__))>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__)))))
#define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
return UnboxValue<decltype(METHODNAME())>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create()))
/***********************************************************************
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)\
fields.Add(L ## #FIELDNAME, 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)\
}\
};\
};
/***********************************************************************
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(\
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(new CustomConstructorInfoImpl<FUNCTIONTYPE>(parameterNames));\
}
#define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddConstructor(\
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,\
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 = 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);\
}
#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,\
new CustomStaticMethodInfoImpl<\
vl::function_lambda::FunctionObjectRetriveType<FUNCTIONTYPE>::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(\
new CustomEventInfoImpl<\
ClassType,\
CustomEventFunctionTypeRetriver<decltype(&ClassType::EVENTNAME)>::Type\
>(this, L ## #EVENTNAME, &ClassType::EVENTNAME)\
);
/***********************************************************************
Property
***********************************************************************/
#define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
nullptr,\
nullptr\
)\
);
#define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\
AddProperty(\
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(\
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(\
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(\
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
/***********************************************************************
.\GUITYPEDESCRIPTORREFLECTION.H
***********************************************************************/
/***********************************************************************
Author: Zihan Chen (vczh)
Licensed under https://github.com/vczh-libraries/License
***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORREFLECTION
#define VCZH_REFLECTION_GUITYPEDESCRIPTORREFLECTION
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(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(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
#define DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(TYPENAME)\
template<>\
struct TypedValueSerializerProvider<TYPENAME>\
{\
static TYPENAME GetDefaultValue();\
static bool Serialize(const TYPENAME& input, WString& output);\
static bool Deserialize(const WString& input, TYPENAME& output);\
static IBoxedValue::CompareResult Compare(const TYPENAME& a, const TYPENAME& b);\
};\
REFLECTION_PREDEFINED_SERIALIZABLE_TYPES(DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER)
#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(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