mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-02-06 03:42:11 +08:00
8058 lines
269 KiB
C++
8058 lines
269 KiB
C++
/***********************************************************************
|
|
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
|
|
DEVELOPER: Zihan Chen(vczh)
|
|
***********************************************************************/
|
|
#include "VlppOS.h"
|
|
#include "Vlpp.h"
|
|
#include "VlppRegex.h"
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEOBJECT.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_DESCRIPTABLEOBJECT
|
|
#define VCZH_REFLECTION_DESCRIPTABLEOBJECT
|
|
|
|
|
|
#if (defined VCZH_DEBUG_NO_REFLECTION) && (defined VCZH_DEBUG_METAONLY_REFLECTION)
|
|
static_assert(false, "Preprocessor VCZH_DEBUG_NO_REFLECTION and VCZH_DEBUG_METAONLY_REFLECTION could not be defined at the same time.")
|
|
#endif
|
|
|
|
#if !(defined VCZH_DEBUG_NO_REFLECTION) && !(defined VCZH_DEBUG_METAONLY_REFLECTION)
|
|
#define VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
#endif
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
class ITypeDescriptor;
|
|
}
|
|
|
|
/***********************************************************************
|
|
DescriptableObject
|
|
***********************************************************************/
|
|
|
|
/// <summary>
|
|
/// <p>
|
|
/// Base class of all reflectable value types (class).
|
|
/// If you want to create a reflectable class, you should inherit from [T:vl.reflection.Description`1].
|
|
/// </p>
|
|
/// <p>
|
|
/// Inheriting from [T:vl.reflection.Description`1] is necessary even if you turned on "VCZH_DEBUG_NO_REFLECTION" preprocessor definition.
|
|
/// In this case, some members will be removed from this class to reduce the object size.
|
|
/// </p>
|
|
/// <p>
|
|
/// <b>Ptr<DescriptableObject></b> is recommended to replace <b>Ptr<Object></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<T></b> is safe to be created directly from a <b>T*</b> hold by another <b>Ptr<T></b>.
|
|
/// This is not allowed for all classes that do not inherit from [T:vl.reflection.Description`1].
|
|
/// </p>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <p>
|
|
/// When a class in Workflow script inherits from a class in C++,
|
|
/// since it is not possible to actually create a class in runtime,
|
|
/// so the created object from this Workflow class is multiple <b>DescriptableObject</b> grouping together.
|
|
/// </p>
|
|
/// <p>
|
|
/// This is called <b>aggregation</b>.
|
|
/// </p>
|
|
/// <p>
|
|
/// In this case, <see cref="SafeAggregationCast`1"/> is required to do pointer casting to a C++ class.
|
|
/// </p>
|
|
/// <p>
|
|
/// To allow a C++ class to be aggregated,
|
|
/// use [T:vl.reflection.AggregatableDescription`1] instead of [T:vl.reflection.Description`1],
|
|
/// and call <see cref="FinalizeAggregation"/> in the destructor.
|
|
/// If A inherits B and they are all aggregatable, do it in both destructors.
|
|
/// </p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// public:
|
|
/// WString data;
|
|
/// };
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// auto myClass = Ptr(new MyClass);
|
|
/// myClass->data = L"Hello, world!";
|
|
///
|
|
/// Ptr<DescriptableObject> obj = myClass;
|
|
/// Console::WriteLine(obj.Cast<MyClass>()->data);
|
|
///
|
|
/// // usually you cannot do this directly
|
|
/// // because obj and myClass share the same reference counter, but myClass2 doesn't
|
|
/// // this will cause the destructor delete MyClass twice and crash
|
|
/// // but it is different when MyClass inherits from Description<MyClass> or AggregatableDescription<MyClass>
|
|
/// auto myClass2 = Ptr<MyClass>(dynamic_cast<MyClass*>(obj.Obj()));
|
|
/// Console::WriteLine(myClass2->data);
|
|
/// }
|
|
/// ]]></example>
|
|
class DescriptableObject
|
|
{
|
|
template<typename T, typename Enabled>
|
|
friend struct vl::ReferenceCounterOperator;
|
|
template<typename T>
|
|
friend class Description;
|
|
|
|
typedef collections::Dictionary<WString, Ptr<Object>> InternalPropertyMap;
|
|
typedef bool(*DestructorProc)(DescriptableObject* obj, bool forceDisposing);
|
|
private:
|
|
atomic_vint referenceCounter;
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
size_t objectSize;
|
|
description::ITypeDescriptor** typeDescriptor;
|
|
#endif
|
|
Ptr<InternalPropertyMap> internalProperties;
|
|
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
bool destructing;
|
|
DescriptableObject** aggregationInfo;
|
|
vint aggregationSize;
|
|
#endif
|
|
|
|
protected:
|
|
DestructorProc sharedPtrDestructorProc;
|
|
|
|
protected:
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
// Returns true if this object inherits other objects by aggregation.</returns>
|
|
bool IsAggregated();
|
|
|
|
// Returnd the number of aggregated base objects.</returns>
|
|
vint GetAggregationSize();
|
|
|
|
// Return the object that inherit this object.</returns>
|
|
DescriptableObject* GetAggregationRoot();
|
|
|
|
// Notice that an object inherit this object, it is called by SetAggregationParent
|
|
void SetAggregationRoot(DescriptableObject* value);
|
|
|
|
// Return the specified aggregated base object
|
|
DescriptableObject* GetAggregationParent(vint index);
|
|
|
|
// Set an aggregated base class
|
|
void SetAggregationParent(vint index, DescriptableObject* value);
|
|
|
|
// Set an aggregated base class
|
|
void SetAggregationParent(vint index, Ptr<DescriptableObject>& value);
|
|
|
|
// Must be called in Workflow generated classes that inherit from aggregatable C++ classes.
|
|
void InitializeAggregation(vint size);
|
|
#endif
|
|
/// <summary>A function that must be called in destructors of all classes inheriting from [T:vl.reflection.AggregatableDescription`1].</summary>
|
|
void FinalizeAggregation();
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
template<typename T>
|
|
void SafeAggregationCast(T*& result)
|
|
{
|
|
auto expected = dynamic_cast<T*>(this);
|
|
if (expected)
|
|
{
|
|
CHECK_ERROR(result == nullptr, L"vl::reflection::DescriptableObject::SafeAggregationCast<T>()#Found multiple ways to do aggregation cast.");
|
|
result = expected;
|
|
}
|
|
if (IsAggregated())
|
|
{
|
|
for (vint i = 0; i < aggregationSize; i++)
|
|
{
|
|
if (auto parent = GetAggregationParent(i))
|
|
{
|
|
parent->SafeAggregationCast<T>(result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
public:
|
|
DescriptableObject();
|
|
virtual ~DescriptableObject();
|
|
|
|
// all fields are describing the object, it would be incorrect if they are copied from one to another.
|
|
DescriptableObject(const DescriptableObject&) : DescriptableObject() {}
|
|
DescriptableObject(DescriptableObject&&) : DescriptableObject() {}
|
|
DescriptableObject& operator=(const DescriptableObject&) { return *this; }
|
|
DescriptableObject& operator=(DescriptableObject&&) { return *this; }
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
/// <summary>
|
|
/// <p>Get the type descriptor that describe the real type of this object.</p>
|
|
/// </summary>
|
|
/// <returns>The real type.</returns>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
description::ITypeDescriptor* GetTypeDescriptor();
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Get an internal property of this object.
|
|
/// Internal properties are totally for customization,
|
|
/// they do not affect the object in anyway.
|
|
/// </summary>
|
|
/// <returns>Value of the internal property of this object.</returns>
|
|
/// <param name="name">Name of the property.</param>
|
|
Ptr<Object> GetInternalProperty(const WString& name);
|
|
/// <summary>
|
|
/// Set an internal property of this object.
|
|
/// Internal properties are totally for customization,
|
|
/// they do not affect the object in anyway.
|
|
/// </summary>
|
|
/// <param name="name">Name of the property.</param>
|
|
/// <param name="value">Value of the internal property of this object.</param>
|
|
void SetInternalProperty(const WString& name, Ptr<Object> value);
|
|
/// <summary>Try to delete this object.</summary>
|
|
/// <returns>Returns true if this operation succeeded. Returns false if the object refuces to be dispose.</returns>
|
|
/// <param name="forceDisposing">Set to true to force disposing this object. If the reference counter is not 0 if you force disposing it, it will raise a [T:vl.reflection.description.ValueNotDisposableException].</param>
|
|
bool Dispose(bool forceDisposing);
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
/// <summary>
|
|
/// <p>Get the aggregation root object, which is the object that inherits this object by aggregation.</p>
|
|
/// </summary>
|
|
/// <returns>The aggregation root object. If this object is not aggregated, or it is the root object of others, than this function return itself.</returns>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
DescriptableObject* SafeGetAggregationRoot();
|
|
|
|
#endif
|
|
/// <summary>Cast the object to another type, this is required when the object is involved in aggregation.</summary>
|
|
/// <returns>The object with the expected type in all involved aggregated objects. It will crash when multiple objects are found to be qualified.</returns>
|
|
/// <typeparam name="T">The expected type to cast.</typeparam>
|
|
/// <remarks>
|
|
/// <p>
|
|
/// A workflow class could inherit from multiple aggregatable C++ classes.
|
|
/// </p>
|
|
/// <p>
|
|
/// In order to do pointer casting correctly,
|
|
/// this function allow you to cast from one aggregated C++ base object to another aggregated C++ base object,
|
|
/// even when these two objects are not involved in inheriting in C++.
|
|
/// </p>
|
|
/// <p>
|
|
/// When <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>on</b>, it performs dynamic_cast.
|
|
/// </p>
|
|
/// </remarks>
|
|
template<typename T>
|
|
T* SafeAggregationCast()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
T* result = nullptr;
|
|
SafeGetAggregationRoot()->SafeAggregationCast<T>(result);
|
|
return result;
|
|
#else
|
|
return dynamic_cast<T*>(this);
|
|
#endif
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// <p>
|
|
/// Inherit from this class when you want to create a reflectable class.
|
|
/// It should be used like this:
|
|
/// <program><code><![CDATA[
|
|
/// class YourClass : public Description<YourClass>
|
|
/// {
|
|
/// ..
|
|
/// };
|
|
/// ]]></code></program>
|
|
/// </p>
|
|
/// <p>
|
|
/// If you want YourClass to be inheritable in scripts,
|
|
/// instead of using Description,
|
|
/// you should use <see cref="AggregatableDescription`1"/>, like this:
|
|
/// <program><code><![CDATA[
|
|
/// class YourClass : public AggregatableDescription<YourClass>
|
|
/// {
|
|
/// ~YourClass()
|
|
/// {
|
|
/// FinalizeAggregation();
|
|
/// }
|
|
/// };
|
|
/// ]]></code></program>
|
|
/// </p>
|
|
/// <p>
|
|
/// After you complete your type,
|
|
/// use the following macros and functions to register your class into the global type table.
|
|
/// </p>
|
|
/// <p>
|
|
/// Some of the predefined type has already been registered.
|
|
/// If your types depend on these types, you should load those types by calling some or all of them:
|
|
/// <ul>
|
|
/// <li>[F:vl.reflection.description.LoadPredefinedTypes]</li>
|
|
/// <li>[F:vl.reflection.description.LoadParsingTypes]</li>
|
|
/// <li>[F:vl.reflection.description.JsonLoadTypes]</li>
|
|
/// <li>[F:vl.reflection.description.XmlLoadTypes]</li>
|
|
/// </ul>
|
|
/// But if you link <b>GacUIReflection.cpp</b> in your project and set <b>VCZH_DEBUG_NO_REFLECTION</b> to off,
|
|
/// all types will be automatically loaded before <b>GuiMain</b> is called.
|
|
/// </p>
|
|
/// <p>
|
|
/// The order does not matter, because content of types are lazily loaded.
|
|
/// </p>
|
|
/// <p>
|
|
/// Everything below should be put in <b>vl::reflection::description</b> namespaces.
|
|
/// <ol>
|
|
/// <li>
|
|
/// <b>(in header files)</b> Create a macro that contains all types that you want to register.
|
|
/// Content in the list will become full names for registered type,
|
|
/// so it is strongly recommended to use the full name.
|
|
/// <program><code><![CDATA[
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespaces::MyClass1)\
|
|
/// F(mynamespaces::MyClass2)\
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>in header files)</b> Connect type names and types:
|
|
/// <program><code><![CDATA[
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>(in cpp files)</b> Connect type names and types:
|
|
/// <program><code><![CDATA[
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>(in cpp files)</b> Register all members:
|
|
/// <ul>
|
|
/// <li>
|
|
/// You will need to define a macro for commas, Whatever name is fine.
|
|
/// <program><code><![CDATA[
|
|
/// #define _ ,
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>enum</b>:
|
|
/// use <b>BEGIN_ENUM_ITEM_MERGABLE</b> instead of <b>BEGIN_ENUM_ITEM</b> if enum items are flags instead of concrete items.
|
|
/// <program><code><![CDATA[
|
|
/// BEGIN_ENUM_ITEM(Season)
|
|
/// ENUM_ITEM(Spring)
|
|
/// ENUM_ITEM(Summer)
|
|
/// ENUM_ITEM(Autumn)
|
|
/// ENUM_ITEM(Winter)
|
|
/// END_ENUM_ITEM(Season)
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>enum class:</b>
|
|
/// use <b>BEGIN_ENUM_ITEM_MERGABLE</b> instead of <b>BEGIN_ENUM_ITEM</b> if enum items are flags instead of concrete items.
|
|
/// <program><code><![CDATA[
|
|
/// BEGIN_ENUM_ITEM(Season)
|
|
/// ENUM_CLASS_ITEM(Spring)
|
|
/// ENUM_CLASS_ITEM(Summer)
|
|
/// ENUM_CLASS_ITEM(Autumn)
|
|
/// ENUM_CLASS_ITEM(Winter)
|
|
/// END_ENUM_ITEM(Season)
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>struct</b>:
|
|
/// It doesn't necessary mean a struct in C++.
|
|
/// Structs in reflection and Workflow script mean value types that carry only data, without methods and inheritance.
|
|
/// <program><code><![CDATA[
|
|
/// BEGIN_STRUCT_MEMBER(Point)
|
|
/// STRUCT_MEMBER(x)
|
|
/// STRUCT_MEMBER(y)
|
|
/// END_STRUCT_MEMBER(Point)
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// <p>
|
|
/// <b>class</b>:
|
|
/// It doesn't necessary mean a class in C++.
|
|
/// Classes in reflection and Workflow script mean reference types.
|
|
/// </p>
|
|
/// <p>
|
|
/// Here are all macros that register content of classes
|
|
/// <ul>
|
|
/// <li>CLASS_MEMBER_BASE</li>
|
|
/// <li>CLASS_MEMBER_FIELD</li>
|
|
/// <li>CLASS_MEMBER_CONSTRUCTOR</li>
|
|
/// <li>CLASS_MEMBER_EXTERNALCTOR(_TEMPLATE)?</li>
|
|
/// <li>CLASS_MEMBER_METHOD(_OVERLOAD)?_RENAME</li>
|
|
/// <li>CLASS_MEMBER_(STATIC_)?METHOD(_OVERLOAD)?</li>
|
|
/// <li>CLASS_MEMBER_(STATIC_)?EXTERNALMETHOD(_TEMPLATE)?</li>
|
|
/// <li>CLASS_MEMBER_PROPERTY(_EVENT)?(_READONLY)?(_FAST)?</li>
|
|
/// <li>CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE</li>
|
|
/// <li>CLASS_MEMBER_EVENT</li>
|
|
/// </ul>
|
|
/// </p>
|
|
/// <p>
|
|
/// <program><code><![CDATA[
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// // 01) Declare a base class (can have multiple base classes).
|
|
/// CLASS_MEMBER_BASE(MyBaseClass)
|
|
///
|
|
/// // 02) Declare a field.
|
|
/// CLASS_MEMBER_FIELD(myField)
|
|
///
|
|
/// // 03) Default constructor that results in a raw pointer.
|
|
/// CLASS_MEMBER_CONSTRUCTIOR(MyClass*(), NO_PARAMETER)
|
|
///
|
|
/// // 04) Default constructor that results in a shared pointer.
|
|
/// CLASS_MEMBER_CONSTRUCTIOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
///
|
|
/// // 05) Constructor with arguments.
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"})
|
|
///
|
|
/// // 06) Inject a global function as a constructor.
|
|
/// CLASS_MEMBER_EXTERNALCTOR(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, mynamespace::CreateMyClass)
|
|
///
|
|
/// // 07) Inject a consturctor and specify how to generate C++ code, "*" means not able to generate.
|
|
/// CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(int, const WString&), {L"numberParameter" _ L"stringParameter"}, CreateMyClass, L"mynamespace::GetMyClass($Arguments)", L"::vl::Func<$Func>(&mynamespace::GetMyClass)")
|
|
/// CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr<MyClass>(), NO_PARAMETER, []()->Ptr<MyClass>{return nullptr;}, L"*", L"*")
|
|
///
|
|
/// // 08) Add unoverloaded functions.
|
|
/// CLASS_MEMBER_METHOD(MyFunction1, NO_PARAMETER)
|
|
/// CLASS_MEMBER_METHOD(MyFunction2, {L"parameter1" _ L"parameter2"})
|
|
///
|
|
/// // 09) Add unoverloaded functions but give different names. Unoverloaded only means in C++, not in renamed functions.
|
|
/// CLASS_MEMBER_METHOD_RENAME(MyNewName1, MyFunction1, NO_PARAMETER)
|
|
/// CLASS_MEMBER_METHOD_RENAME(MyNewName2, MyFunction2, {L"parameter1" _ L"parameter2"})
|
|
///
|
|
/// // 10) Add overloaded functions, with function type specified in method pointers
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, NO_PARAMETER, int(MyClass::*)())
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter"}, int(MyClass::*)(int))
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD(MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
|
|
///
|
|
/// // 11) Add overloaded functions but give different names.
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName3, MyFunction3, NO_PARAMETER, int(MyClass::*)())
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter"}, int(MyClass::*)(int))
|
|
/// CLASS_MEMBER_METHOD_OVERLOAD_RENAME(MyNewName4, MyFunction3, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&))
|
|
///
|
|
/// // 12) Inject global functions as methods:
|
|
/// CLASS_MEMBER_EXTERNALMETHOD(MyNewName5, {L"parameter"}, int(MyClass::*)(int), mynamespace::AGlobalFunction)
|
|
///
|
|
/// // 13) Inject a method and specify how to generate C++ code, "*" means not able to generate.
|
|
/// CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(MyNewName5, {L"parameter1" _ L"parameter2"}, int(MyClass::*)(int, const WString&), [](MyClass* a, int b, const WString& c){return 0;}, L"*", L"*")
|
|
///
|
|
/// // 14) Add unoverloaded static functions
|
|
/// CLASS_MEMBER_STATIC_METHOD(MyFunction4, NO_PARAMETER)
|
|
/// CLASS_MEMBER_STATIC_METHOD(MyFunction5, {L"parameter1" _ L"parameter2"})
|
|
///
|
|
/// // 15) Add overloaded static functions
|
|
/// CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, NO_PARAMETER, int(*)())
|
|
/// CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, {L"parameter"}, int(*)(int))
|
|
/// CLASS_MEMBER_STATIC_METHOD_OVERLOAD(MyFunction6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&))
|
|
///
|
|
/// // 16) Inject global functions as static methods:
|
|
/// CLASS_MEMBER_STATIC_EXTERNALMETHOD(MyNewName6, {L"parameter"}, int(*)(int), mynamespace::AGlobalFunction2)
|
|
///
|
|
/// // 17) Inject a static method and specify how to generate C++ code, "*" means not able to generate.
|
|
/// CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(MyNewName6, {L"parameter1" _ L"parameter2"}, int(*)(int, const WString&), [](int b, const WString& c){return 0;}, L"*")
|
|
///
|
|
/// // 18) Add a getter function as a property
|
|
/// CLASS_MEMBER_PROPERTY_READONLY_FAST(X)
|
|
/// // which is short for
|
|
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
|
|
/// CLASS_MEMBER_PROPERTY_READONLY(X, GetX)
|
|
///
|
|
/// // 19) Add a pair of getter and setter functions as a property
|
|
/// CLASS_MEMBER_PROPERTY_FAST(X)
|
|
/// // which is short for
|
|
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
|
|
/// CLASS_MEMBER_METHOD(SetX, {L"value"})
|
|
/// CLASS_MEMBER_PROPERTY(X, GetX, SetX)
|
|
///
|
|
/// // 20) Add a getter function as a property with a property changed event
|
|
/// CLASS_MEMBER_EVENT(XChanged)
|
|
/// CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(X, XChanged)
|
|
/// // which is short for
|
|
/// CLASS_MEMBER_EVENT(XChanged)
|
|
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
|
|
/// CLASS_MEMBER_PROPERTY_EVENT_READONLY(X, GetX, XChanged)
|
|
///
|
|
/// // 21) Add a pair of getter and setter functions as a property with a property changed event
|
|
/// CLASS_MEMBER_EVENT(XChanged)
|
|
/// CLASS_MEMBER_PROPERTY_EVENT_FAST(X, XChanged)
|
|
/// // which is short for
|
|
/// CLASS_MEMBER_EVENT(XChanged)
|
|
/// CLASS_MEMBER_METHOD(GetX, NO_PARAMETER)
|
|
/// CLASS_MEMBER_METHOD(SetX, {L"value"})
|
|
/// CLASS_MEMBER_PROPERTY_EVENT(X, GetX, SetX, XChanged)
|
|
///
|
|
/// 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<[T:vl.reflection.description.IValueInterfaceProxy]> as a parameter, so that a Workflow script class could implement this interface.</li>
|
|
/// </ul>
|
|
/// </p>
|
|
/// <p>
|
|
/// Suppose you have an interface like this:
|
|
/// <program><code><![CDATA[
|
|
/// class IMyInterface : public virtual IDescriptable, public Description<IMyInterface>
|
|
/// {
|
|
/// public:
|
|
/// int GetX();
|
|
/// void SetX(int value);
|
|
/// };
|
|
/// ]]></code></program>
|
|
/// </p>
|
|
/// <p>
|
|
/// If you want to allow a Workflow script class implement this interface, you should first add a proxy like this:
|
|
/// <program><code><![CDATA[
|
|
/// #pragma warning(push)
|
|
/// #pragma warning(disable:4250)
|
|
/// BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(IMyInterface)
|
|
/// // or BEGIN_INTERFACE_PROXY_RAWPTR(IMyInterface, baseInterfaces...)
|
|
/// // or BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IMyInterface)
|
|
/// // or BEGIN_INTERFACE_PROXY_SHAREDPTR(IMyInterface, baseInterfaces...)
|
|
/// int GetX()override
|
|
/// {
|
|
/// INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetX)
|
|
/// }
|
|
///
|
|
/// void SetX(int value)override
|
|
/// {
|
|
/// INVOKE_INTERFACE_PROXY(SetX, value)
|
|
/// }
|
|
/// END_INTERFACE_PROXY(IMyInterface)
|
|
/// #pragma warning(pop)
|
|
/// ]]></code></program>
|
|
/// </p>
|
|
/// <p>
|
|
/// And then use this code to register the interface:
|
|
/// <program><code><![CDATA[
|
|
/// BEGIN_INTERFACE_MEMBER(IMyInterface)
|
|
/// ...
|
|
/// END_INTERFACE_MEMBER(IMyInterface)
|
|
/// ]]></code></program>
|
|
/// </p>
|
|
/// <p>
|
|
/// Everything else is the same as registering classes.
|
|
/// Use <b>BEGIN_INTERFACE_MEMBER_NOPROXY</b> to register an interface without a proxy,
|
|
/// which means a Workflow script class cannot implement this interface.
|
|
/// </p>
|
|
/// </li>
|
|
/// <li>
|
|
/// Undefine the macro for comma:
|
|
/// <program><code><![CDATA[
|
|
/// #undef _
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// <li>
|
|
/// <b>(in cpp files)</b> Create a type loader:
|
|
/// <program><code><![CDATA[
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// <li>
|
|
/// Before using reflection on registered types, you need to register the type loader:
|
|
/// <program><code><![CDATA[
|
|
/// vl::reflection::description::GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// ]]></code></program>
|
|
/// </li>
|
|
/// </ol>
|
|
/// </p>
|
|
/// </summary>
|
|
/// <typeparam name="T">Type that inherit this class.</typeparam>
|
|
template<typename T>
|
|
class Description : public virtual DescriptableObject
|
|
{
|
|
protected:
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
static description::ITypeDescriptor* associatedTypeDescriptor;
|
|
#endif
|
|
public:
|
|
Description()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
if(objectSize<sizeof(T))
|
|
{
|
|
objectSize=sizeof(T);
|
|
if(!typeDescriptor || !*typeDescriptor || associatedTypeDescriptor)
|
|
{
|
|
typeDescriptor=&associatedTypeDescriptor;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
static description::ITypeDescriptor* GetAssociatedTypeDescriptor()
|
|
{
|
|
return associatedTypeDescriptor;
|
|
}
|
|
|
|
static void SetAssociatedTypeDescriptor(description::ITypeDescriptor* typeDescroptor)
|
|
{
|
|
associatedTypeDescriptor=typeDescroptor;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
template<typename T>
|
|
description::ITypeDescriptor* Description<T>::associatedTypeDescriptor = 0;
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
AggregatableDescription
|
|
***********************************************************************/
|
|
|
|
/// <summary>
|
|
/// Inherit from this class when you want to create a reflectable class that can be inherited by Workflow script classes.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type that inherit this class.</typeparam>
|
|
template<typename T>
|
|
class AggregatableDescription : public Description<T>
|
|
{
|
|
};
|
|
|
|
/***********************************************************************
|
|
IDescriptable
|
|
***********************************************************************/
|
|
|
|
/// <summary>Base type of all reflectable interfaces. All reflectable interface types should be virtual inherited.</summary>
|
|
class IDescriptable : public virtual Interface, public Description<IDescriptable>
|
|
{
|
|
public:
|
|
~IDescriptable(){}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ReferenceCounterOperator
|
|
***********************************************************************/
|
|
}
|
|
|
|
template<typename T>
|
|
struct ReferenceCounterOperator<T, std::enable_if_t<std::is_convertible_v<T*, reflection::DescriptableObject*>>>
|
|
{
|
|
static __forceinline atomic_vint* CreateCounter(T* reference)
|
|
{
|
|
reflection::DescriptableObject* obj=reference;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (obj->IsAggregated())
|
|
{
|
|
if (auto root = obj->GetAggregationRoot())
|
|
{
|
|
return &root->referenceCounter;
|
|
}
|
|
}
|
|
#endif
|
|
return &obj->referenceCounter;
|
|
}
|
|
|
|
static __forceinline void DeleteReference(atomic_vint* counter, void* reference)
|
|
{
|
|
reflection::DescriptableObject* obj=(T*)reference;
|
|
obj->Dispose(false);
|
|
}
|
|
};
|
|
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Exceptions
|
|
***********************************************************************/
|
|
|
|
class TypeDescriptorException abstract : public Exception
|
|
{
|
|
public:
|
|
TypeDescriptorException(const WString& message)
|
|
:Exception(message)
|
|
{
|
|
}
|
|
};
|
|
|
|
class ObjectDisposedException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ObjectDisposedException()
|
|
:TypeDescriptorException(L"The referenced native object has been disposed.")
|
|
{
|
|
}
|
|
};
|
|
|
|
class ValueNotDisposableException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ValueNotDisposableException()
|
|
:TypeDescriptorException(L"Cannot dispose an object whose reference counter is not 0.")
|
|
{
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEVALUE.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_DESCRIPTABLEVALUE
|
|
#define VCZH_REFLECTION_DESCRIPTABLEVALUE
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
class ITypeInfo;
|
|
class IMethodGroupInfo;
|
|
class IMethodInfo;
|
|
class IPropertyInfo;
|
|
class IEventInfo;
|
|
class IEventHandler;
|
|
class IValueFunctionProxy;
|
|
}
|
|
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Value
|
|
***********************************************************************/
|
|
|
|
enum class PredefinedBoxableType : vint
|
|
{
|
|
PBT_Unknown = -1,
|
|
PBT_S8, PBT_S16, PBT_S32, PBT_S64,
|
|
PBT_U8, PBT_U16, PBT_U32, PBT_U64,
|
|
PBT_F32, PBT_F64,
|
|
PBT_BOOL,
|
|
PBT_WCHAR,
|
|
PBT_STRING,
|
|
PBT_LOCALE,
|
|
PBT_DATETIME,
|
|
};
|
|
|
|
class IBoxedValue : public virtual IDescriptable, public Description<IBoxedValue>
|
|
{
|
|
public:
|
|
enum CompareResult
|
|
{
|
|
Smaller,
|
|
Greater,
|
|
Equal,
|
|
NotComparable,
|
|
};
|
|
|
|
virtual PredefinedBoxableType GetBoxableType() = 0;
|
|
virtual Ptr<IBoxedValue> Copy() = 0;
|
|
virtual CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue) = 0;
|
|
};
|
|
|
|
/// <summary>A type to store all values of reflectable types.</summary>
|
|
/// <remarks>
|
|
/// To convert between <b>Value</b> and its real C++ type, the following functions are recommended:
|
|
/// <ul>
|
|
/// <li>[F:vl.reflection.description.BoxValue`1]</li>
|
|
/// <li>[F:vl.reflection.description.UnboxValue`1]</li>
|
|
/// <li>[F:vl.reflection.description.BoxParameter`1]</li>
|
|
/// <li>[F:vl.reflection.description.UnboxParameter`1]</li>
|
|
/// </ul>
|
|
/// </remarks>
|
|
class Value : public Object
|
|
{
|
|
public:
|
|
/// <summary>How the value is stored.</summary>
|
|
enum ValueType
|
|
{
|
|
/// <summary>The value is null.</summary>
|
|
Null,
|
|
/// <summary>The reference value is stored using a raw pointer.</summary>
|
|
RawPtr,
|
|
/// <summary>The reference value is stored using a shared pointer.</summary>
|
|
SharedPtr,
|
|
/// <summary>The value is stored by boxing.</summary>
|
|
BoxedValue,
|
|
};
|
|
protected:
|
|
ValueType valueType;
|
|
DescriptableObject* rawPtr;
|
|
Ptr<DescriptableObject> sharedPtr;
|
|
Ptr<IBoxedValue> boxedValue;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
ITypeDescriptor* typeDescriptor;
|
|
#endif
|
|
|
|
Value(DescriptableObject* value);
|
|
Value(Ptr<DescriptableObject> value);
|
|
Value(Ptr<IBoxedValue> value, ITypeDescriptor* associatedTypeDescriptor);
|
|
public:
|
|
/// <summary>Create a null value.</summary>
|
|
Value();
|
|
Value(const Value& value);
|
|
Value& operator=(const Value& value);
|
|
|
|
friend std::partial_ordering operator<=>(const Value& a, const Value& b);
|
|
friend bool operator==(const Value& a, const Value& b) { return (a <=> b) == 0; }
|
|
|
|
/// <summary>Find out how the value is stored.</summary>
|
|
/// <returns>Returns How the value is stored.</returns>
|
|
ValueType GetValueType()const;
|
|
/// <summary>Get the stored raw pointer if <b>GetValueType()</b> returns <b>RawPtr</b> or <b>SharedPtr</b>.</summary>
|
|
/// <returns>The stored raw pointer. Returns null if failed.</returns>
|
|
DescriptableObject* GetRawPtr()const;
|
|
/// <summary>Get the stored shared pointer if <b>GetValueType()</b> returns <b>SharedPtr</b>.</summary>
|
|
/// <returns>The stored shared pointer. Returns null if failed.</returns>
|
|
Ptr<DescriptableObject> GetSharedPtr()const;
|
|
/// <summary>Get the stored value if <b>GetValueType()</b> returns <b>BoxedValue</b>.</summary>
|
|
/// <returns>The stored text. Returns empty if failed.</returns>
|
|
Ptr<IBoxedValue> GetBoxedValue()const;
|
|
/// <summary>Test if this value isnull.</summary>
|
|
/// <returns>Returns true if this value is null.</returns>
|
|
bool IsNull()const;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
/// <summary>Get the real type of the stored object.</summary>
|
|
/// <returns>The real type. Returns null if the value is null.</returns>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
ITypeDescriptor* GetTypeDescriptor()const;
|
|
WString GetTypeFriendlyName()const;
|
|
bool CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const;
|
|
bool CanConvertTo(ITypeInfo* targetType)const;
|
|
#endif
|
|
|
|
/// <summary>Create a value from a raw pointer.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="value">The raw pointer to store.</param>
|
|
static Value From(DescriptableObject* value);
|
|
/// <summary>Create a value from a shared pointer.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="value">The shared pointer to store.</param>
|
|
static Value From(Ptr<DescriptableObject> value);
|
|
/// <summary>Create a boxed value.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="value">The boxed value to store.</param>
|
|
/// <param name="type">The type of the boxed value.</param>
|
|
static Value From(Ptr<IBoxedValue> value, ITypeDescriptor* type);
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
static IMethodInfo* SelectMethod(IMethodGroupInfo* methodGroup, collections::Array<Value>& arguments);
|
|
|
|
/// <summary>Call the default constructor of the specified type to create a value.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="type">The type to create the value.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
static Value Create(ITypeDescriptor* type);
|
|
|
|
/// <summary>Call the constructor of the specified type to create a value.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="type">The type to create the value.</param>
|
|
/// <param name="arguments">Arguments for the constructor.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// public:
|
|
/// MyClass()
|
|
/// :data(L"Hello, world!")
|
|
/// {
|
|
/// }
|
|
///
|
|
/// MyClass(const WString& _data)
|
|
/// :data(_data)
|
|
/// {
|
|
/// }
|
|
///
|
|
/// WString data;
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(const WString&), { L"data" })
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto myClass = Value::Create(GetTypeDescriptor(L"mynamespace::MyClass"), (Value_xs(), WString(L"Hello, world!!!")));
|
|
///
|
|
/// auto ptrMyClass1 = UnboxValue<Ptr<MyClass>>(myClass);
|
|
/// Console::WriteLine(ptrMyClass1->data);
|
|
///
|
|
/// Ptr<MyClass> ptrMyClass2;
|
|
/// UnboxParameter(myClass, ptrMyClass2);
|
|
/// Console::WriteLine(ptrMyClass2->data);
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
static Value Create(ITypeDescriptor* type, collections::Array<Value>& arguments);
|
|
|
|
/// <summary>Call the default constructor of the specified type to create a value.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="typeName">The registered full name for the type to create the value.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
static Value Create(const WString& typeName);
|
|
|
|
/// <summary>Call the constructor of the specified type to create a value.</summary>
|
|
/// <returns>The created value.</returns>
|
|
/// <param name="typeName">The registered full name for the type to create the value.</param>
|
|
/// <param name="arguments">Arguments for the constructor.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// public:
|
|
/// MyClass()
|
|
/// :data(L"Hello, world!")
|
|
/// {
|
|
/// }
|
|
///
|
|
/// MyClass(const WString& _data)
|
|
/// :data(_data)
|
|
/// {
|
|
/// }
|
|
///
|
|
/// WString data;
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(const WString&), { L"data" })
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto myClass = Value::Create(L"mynamespace::MyClass", (Value_xs(), WString(L"Hello, world!!!")));
|
|
///
|
|
/// auto ptrMyClass1 = UnboxValue<Ptr<MyClass>>(myClass);
|
|
/// Console::WriteLine(ptrMyClass1->data);
|
|
///
|
|
/// Ptr<MyClass> ptrMyClass2;
|
|
/// UnboxParameter(myClass, ptrMyClass2);
|
|
/// Console::WriteLine(ptrMyClass2->data);
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
static Value Create(const WString& typeName, collections::Array<Value>& arguments);
|
|
|
|
/// <summary>Call a static method of the specified type.</summary>
|
|
/// <returns>The return value from that method.</returns>
|
|
/// <param name="typeName">The registered full name for the type.</param>
|
|
/// <param name="name">The registered name for the method.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
static Value InvokeStatic(const WString& typeName, const WString& name);
|
|
|
|
/// <summary>Call a static method of the specified type.</summary>
|
|
/// <returns>The return value from that method.</returns>
|
|
/// <param name="typeName">The registered full name for the type.</param>
|
|
/// <param name="name">The registered name for the method.</param>
|
|
/// <param name="arguments">Arguments for the method.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// public:
|
|
/// static void PrintHelloWorld(const WString& name)
|
|
/// {
|
|
/// Console::WriteLine(L"Hello, " + name + L"!");
|
|
/// }
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_STATIC_METHOD(PrintHelloWorld, { L"name" })
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// Value::InvokeStatic(L"mynamespace::MyClass", L"PrintHelloWorld", (Value_xs(), WString(L"Gaclib")));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
static Value InvokeStatic(const WString& typeName, const WString& name, collections::Array<Value>& arguments);
|
|
|
|
/// <summary>Call the getter function for a property.</summary>
|
|
/// <returns>The value of the property.</returns>
|
|
/// <param name="name">The registered name for the property.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// private:
|
|
/// WString prop;
|
|
/// public:
|
|
/// WString field;
|
|
///
|
|
/// WString GetProp() { return prop; };
|
|
/// void SetProp(const WString& value) { prop = value; }
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
/// CLASS_MEMBER_FIELD(field)
|
|
/// CLASS_MEMBER_PROPERTY_FAST(Prop)
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto td = GetTypeDescriptor(L"mynamespace::MyClass");
|
|
/// auto myClass = Value::Create(td);
|
|
///
|
|
/// myClass.SetProperty(L"field", BoxValue<WString>(L"Hello, world!"));
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Hello, Gaclib!"));
|
|
///
|
|
/// Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"field")));
|
|
/// Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"Prop")));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
Value GetProperty(const WString& name)const;
|
|
|
|
/// <summary>Call the setter function for a property.</summary>
|
|
/// <param name="name">The registered name for the property.</param>
|
|
/// <param name="newValue">The value to set the property.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// private:
|
|
/// WString prop;
|
|
/// public:
|
|
/// WString field;
|
|
///
|
|
/// WString GetProp() { return prop; };
|
|
/// void SetProp(const WString& value) { prop = value; }
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
/// CLASS_MEMBER_FIELD(field)
|
|
/// CLASS_MEMBER_PROPERTY_FAST(Prop)
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto td = GetTypeDescriptor(L"mynamespace::MyClass");
|
|
/// auto myClass = Value::Create(td);
|
|
///
|
|
/// myClass.SetProperty(L"field", BoxValue<WString>(L"Hello, world!"));
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Hello, Gaclib!"));
|
|
///
|
|
/// Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"field")));
|
|
/// Console::WriteLine(UnboxValue<WString>(myClass.GetProperty(L"Prop")));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
void SetProperty(const WString& name, const Value& newValue);
|
|
|
|
/// <summary>Call a non-static method.</summary>
|
|
/// <returns>The return value from that method.</returns>
|
|
/// <param name="name">The registered name for the method.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
Value Invoke(const WString& name)const;
|
|
|
|
/// <summary>Call a non-static method.</summary>
|
|
/// <returns>The return value from that method.</returns>
|
|
/// <param name="name">The registered name for the method.</param>
|
|
/// <param name="arguments">Arguments for the method.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class MyClass : public Object, public Description<MyClass>
|
|
/// {
|
|
/// public:
|
|
/// void PrintHelloWorld(const WString& name)
|
|
/// {
|
|
/// Console::WriteLine(L"Hello, " + name + L"!");
|
|
/// }
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::MyClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(MyClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<MyClass>(), NO_PARAMETER)
|
|
/// CLASS_MEMBER_METHOD(PrintHelloWorld, { L"name" })
|
|
/// END_CLASS_MEMBER(MyClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto td = GetTypeDescriptor(L"mynamespace::MyClass");
|
|
/// auto myClass = Value::Create(td);
|
|
/// myClass.Invoke(L"PrintHelloWorld", (Value_xs(), WString(L"Gaclib")));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
Value Invoke(const WString& name, collections::Array<Value>& arguments)const;
|
|
|
|
/// <summary>Attach a callback function for the event.</summary>
|
|
/// <returns>The event handler for this attachment. You need to keep it to detach the callback function.</returns>
|
|
/// <param name="name">The registered name for the event.</param>
|
|
/// <param name="function">The callback function.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><
|
|
/// {
|
|
/// Console::WriteLine(L"myClass.Prop changed: " + oldProp + L" -> " + newProp);
|
|
/// };
|
|
/// auto handler = myClass.AttachEvent(L"PropChanged", BoxParameter(callbackFunction));
|
|
///
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"One"));
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Two"));
|
|
/// myClass.DetachEvent(L"PropChanged", handler);
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Three"));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
Ptr<IEventHandler> AttachEvent(const WString& name, const Value& function)const;
|
|
|
|
/// <summary>Detach a callback function from the event.</summary>
|
|
/// <returns>Returns true if this operation succeeded.</returns>
|
|
/// <param name="name">The registered name for the event.</param>
|
|
/// <param name="handler">The event handler returned from <see cref="AttachEvent"/>.</param>
|
|
/// <remarks>
|
|
/// <p>Only available when <b>VCZH_DEBUG_NO_REFLECTION</b> is <b>off</b>.</p>
|
|
/// </remarks>
|
|
/// <example><
|
|
/// {
|
|
/// Console::WriteLine(L"myClass.Prop changed: " + oldProp + L" -> " + newProp);
|
|
/// };
|
|
/// auto handler = myClass.AttachEvent(L"PropChanged", BoxParameter(callbackFunction));
|
|
///
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"One"));
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Two"));
|
|
/// myClass.DetachEvent(L"PropChanged", handler);
|
|
/// myClass.SetProperty(L"Prop", BoxValue<WString>(L"Three"));
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
bool DetachEvent(const WString& name, Ptr<IEventHandler> handler)const;
|
|
#endif
|
|
|
|
/// <summary>Dispose the object if <b>GetValueType()</b> returns <b>RawPtr</b>.</summary>
|
|
/// <returns>
|
|
/// Returns true if the object is disposed.
|
|
/// Returns false if the object cannot be disposed.
|
|
/// An exception will be thrown if the reference counter is not 0.
|
|
///</returns>
|
|
/// <example><![CDATA[
|
|
/// // reflectable C++ types
|
|
///
|
|
/// namespace mynamespace
|
|
/// {
|
|
/// class SharedClass : public Object, public Description<SharedClass>
|
|
/// {
|
|
/// public:
|
|
/// SharedClass()
|
|
/// {
|
|
/// Console::WriteLine(L"SharedClass::SharedClass()");
|
|
/// }
|
|
///
|
|
/// ~SharedClass()
|
|
/// {
|
|
/// Console::WriteLine(L"SharedClass::~SharedClass()");
|
|
/// }
|
|
/// };
|
|
///
|
|
/// class RawClass : public Object, public Description<RawClass>
|
|
/// {
|
|
/// public:
|
|
/// RawClass()
|
|
/// {
|
|
/// Console::WriteLine(L"RawClass::RawClass()");
|
|
/// }
|
|
///
|
|
/// ~RawClass()
|
|
/// {
|
|
/// Console::WriteLine(L"RawClass::~RawClass()");
|
|
/// }
|
|
/// };
|
|
/// }
|
|
///
|
|
/// #define MY_TYPELIST(F)\
|
|
/// F(mynamespace::SharedClass)\
|
|
/// F(mynamespace::RawClass)\
|
|
///
|
|
/// // it is recommended to put the content below in a separated header file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// MY_TYPELIST(DECL_TYPE_INFO)
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // it is recommended to put the content below in a separated cpp file
|
|
///
|
|
/// namespace vl
|
|
/// {
|
|
/// namespace reflection
|
|
/// {
|
|
/// namespace description
|
|
/// {
|
|
/// using namespace mynamespace;
|
|
///
|
|
/// #define _ ,
|
|
///
|
|
/// MY_TYPELIST(IMPL_CPP_TYPE_INFO)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(SharedClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(Ptr<SharedClass>(), NO_PARAMETER)
|
|
/// END_CLASS_MEMBER(SharedClass)
|
|
///
|
|
/// BEGIN_CLASS_MEMBER(RawClass)
|
|
/// CLASS_MEMBER_CONSTRUCTOR(RawClass*(), NO_PARAMETER)
|
|
/// END_CLASS_MEMBER(RawClass)
|
|
///
|
|
/// #undef _
|
|
/// }
|
|
/// }
|
|
/// }
|
|
///
|
|
/// class MyTypeLoader : public Object, public ITypeLoader
|
|
/// {
|
|
/// public:
|
|
/// void Load(ITypeManager* manager)
|
|
/// {
|
|
/// MY_TYPELIST(ADD_TYPE_INFO)
|
|
/// }
|
|
///
|
|
/// void Unload(ITypeManager* manager)
|
|
/// {
|
|
/// }
|
|
/// };
|
|
///
|
|
/// // main function
|
|
///
|
|
/// int main()
|
|
/// {
|
|
/// LoadPredefinedTypes();
|
|
/// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader);
|
|
/// GetGlobalTypeManager()->Load();
|
|
/// {
|
|
/// auto sharedClass = Value::Create(L"mynamespace::SharedClass");
|
|
/// auto rawClass = Value::Create(L"mynamespace::RawClass");
|
|
///
|
|
/// Console::WriteLine(L"sharedClass is " + WString(sharedClass.GetValueType() == Value::SharedPtr ? L"SharedPtr" : L"RawPtr"));
|
|
/// Console::WriteLine(L"rawClass is " + WString(rawClass.GetValueType() == Value::SharedPtr ? L"SharedPtr" : L"RawPtr"));
|
|
///
|
|
/// rawClass.DeleteRawPtr();
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
bool DeleteRawPtr();
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\DESCRIPTABLEINTERFACES.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_DESCRIPTABLEINTERFACES
|
|
#define VCZH_REFLECTION_DESCRIPTABLEINTERFACES
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
class IValueReadonlyList;
|
|
|
|
template<typename T>
|
|
struct TypedValueSerializerProvider;
|
|
}
|
|
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
ValueType
|
|
***********************************************************************/
|
|
|
|
namespace pbt_selector
|
|
{
|
|
template<PredefinedBoxableType _Value>
|
|
struct SelectorBase { static constexpr PredefinedBoxableType Value = _Value; };
|
|
|
|
template<typename T> struct Selector : SelectorBase<PredefinedBoxableType::PBT_Unknown> {};
|
|
|
|
template<> struct Selector<vint8_t> : SelectorBase<PredefinedBoxableType::PBT_S8> {};
|
|
template<> struct Selector<vint16_t> : SelectorBase<PredefinedBoxableType::PBT_S16> {};
|
|
template<> struct Selector<vint32_t> : SelectorBase<PredefinedBoxableType::PBT_S32> {};
|
|
template<> struct Selector<vint64_t> : SelectorBase<PredefinedBoxableType::PBT_S64> {};
|
|
|
|
template<> struct Selector<vuint8_t> : SelectorBase<PredefinedBoxableType::PBT_U8> {};
|
|
template<> struct Selector<vuint16_t> : SelectorBase<PredefinedBoxableType::PBT_U16> {};
|
|
template<> struct Selector<vuint32_t> : SelectorBase<PredefinedBoxableType::PBT_U32> {};
|
|
template<> struct Selector<vuint64_t> : SelectorBase<PredefinedBoxableType::PBT_U64> {};
|
|
|
|
template<> struct Selector<float> : SelectorBase<PredefinedBoxableType::PBT_F32> {};
|
|
template<> struct Selector<double> : SelectorBase<PredefinedBoxableType::PBT_F64> {};
|
|
|
|
template<> struct Selector<bool> : SelectorBase<PredefinedBoxableType::PBT_BOOL> {};
|
|
template<> struct Selector<wchar_t> : SelectorBase<PredefinedBoxableType::PBT_WCHAR> {};
|
|
template<> struct Selector<WString> : SelectorBase<PredefinedBoxableType::PBT_STRING> {};
|
|
template<> struct Selector<Locale> : SelectorBase<PredefinedBoxableType::PBT_LOCALE> {};
|
|
template<> struct Selector<DateTime> : SelectorBase<PredefinedBoxableType::PBT_DATETIME> {};
|
|
}
|
|
|
|
class IValueType : public virtual IDescriptable, public Description<IValueType>
|
|
{
|
|
public:
|
|
template<typename T>
|
|
class TypedBox : public IBoxedValue
|
|
{
|
|
public:
|
|
T value;
|
|
|
|
TypedBox()
|
|
:value{}
|
|
{
|
|
}
|
|
|
|
TypedBox(const T& _value)
|
|
:value(_value)
|
|
{
|
|
}
|
|
|
|
PredefinedBoxableType GetBoxableType()override
|
|
{
|
|
return pbt_selector::Selector<T>::Value;
|
|
}
|
|
|
|
Ptr<IBoxedValue> Copy()override
|
|
{
|
|
return Ptr(new TypedBox<T>(value));
|
|
}
|
|
|
|
CompareResult ComparePrimitive(Ptr<IBoxedValue> boxedValue)override
|
|
{
|
|
if (auto typedBox = boxedValue.Cast<TypedBox<T>>())
|
|
{
|
|
auto r = value <=> typedBox->value;
|
|
if constexpr (std::is_same_v<decltype(r), std::partial_ordering>)
|
|
{
|
|
if (r == std::partial_ordering::unordered) return IBoxedValue::NotComparable;
|
|
}
|
|
if (r < 0) return IBoxedValue::Smaller;
|
|
if (r > 0) return IBoxedValue::Greater;
|
|
return IBoxedValue::Equal;
|
|
}
|
|
return IBoxedValue::NotComparable;
|
|
}
|
|
};
|
|
|
|
virtual Value CreateDefault() = 0;
|
|
};
|
|
|
|
class IEnumType : public virtual IDescriptable, public Description<IEnumType>
|
|
{
|
|
public:
|
|
virtual bool IsFlagEnum() = 0;
|
|
virtual vint GetItemCount() = 0;
|
|
virtual WString GetItemName(vint index) = 0;
|
|
virtual vuint64_t GetItemValue(vint index) = 0;
|
|
virtual vint IndexOfItem(WString name) = 0;
|
|
|
|
virtual Value ToEnum(vuint64_t value) = 0;
|
|
virtual vuint64_t FromEnum(const Value& value) = 0;
|
|
};
|
|
|
|
class ISerializableType : public virtual IDescriptable, public Description<ISerializableType>
|
|
{
|
|
public:
|
|
virtual bool Serialize(const Value& input, WString& output) = 0;
|
|
virtual bool Deserialize(const WString& input, Value& output) = 0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor (type)
|
|
***********************************************************************/
|
|
|
|
enum class TypeInfoHint
|
|
{
|
|
Normal,
|
|
LazyList,
|
|
Array,
|
|
List,
|
|
SortedList,
|
|
ObservableList,
|
|
Dictionary,
|
|
NativeCollectionReference,
|
|
};
|
|
|
|
class ITypeInfo : public virtual IDescriptable, public Description<ITypeInfo>
|
|
{
|
|
public:
|
|
enum Decorator
|
|
{
|
|
RawPtr,
|
|
SharedPtr,
|
|
Nullable,
|
|
TypeDescriptor,
|
|
Generic,
|
|
};
|
|
|
|
virtual Decorator GetDecorator() = 0;
|
|
virtual TypeInfoHint GetHint() = 0;
|
|
virtual ITypeInfo* GetElementType() = 0;
|
|
virtual ITypeDescriptor* GetTypeDescriptor() = 0;
|
|
virtual vint GetGenericArgumentCount() = 0;
|
|
virtual ITypeInfo* GetGenericArgument(vint index) = 0;
|
|
virtual WString GetTypeFriendlyName() = 0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor (basic)
|
|
***********************************************************************/
|
|
|
|
class 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<IValueReadonlyList> arguments)=0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor (property)
|
|
***********************************************************************/
|
|
|
|
class IPropertyInfo : public virtual IMemberInfo, public Description<IPropertyInfo>
|
|
{
|
|
public:
|
|
class ICpp : public virtual IDescriptable, public Description<ICpp>
|
|
{
|
|
public:
|
|
/*
|
|
Arguments:
|
|
$Type: C++ full type name
|
|
$Name: Property name
|
|
$This: Expression for the "this" argument
|
|
Default:
|
|
Struct: $This.$Name
|
|
Class: $This->$Name
|
|
Example:
|
|
Token in syntax tree: $This->$Name.value
|
|
|
|
GetReferenceTemplate() == L"*":
|
|
This property does not exist in C++
|
|
*/
|
|
virtual const WString& GetReferenceTemplate() = 0;
|
|
};
|
|
/*
|
|
Priority:
|
|
1. Use ICpp
|
|
2. Use ICpp from getter and setter
|
|
3. Use default
|
|
*/
|
|
virtual ICpp* GetCpp() = 0;
|
|
|
|
virtual bool IsReadable()=0;
|
|
virtual bool IsWritable()=0;
|
|
virtual ITypeInfo* GetReturn()=0;
|
|
virtual IMethodInfo* GetGetter()=0;
|
|
virtual IMethodInfo* GetSetter()=0;
|
|
virtual IEventInfo* GetValueChangedEvent()=0;
|
|
virtual Value GetValue(const Value& thisObject)=0;
|
|
virtual void SetValue(Value& thisObject, const Value& newValue)=0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor (method)
|
|
***********************************************************************/
|
|
|
|
class IParameterInfo : public virtual IMemberInfo, public Description<IParameterInfo>
|
|
{
|
|
public:
|
|
virtual ITypeInfo* GetType()=0;
|
|
virtual IMethodInfo* GetOwnerMethod()=0;
|
|
};
|
|
|
|
class IMethodInfo : public virtual IMemberInfo, public Description<IMethodInfo>
|
|
{
|
|
public:
|
|
class ICpp : public virtual IDescriptable, public Description<ICpp>
|
|
{
|
|
public:
|
|
/*
|
|
Arguments:
|
|
$Type: C++ full type name
|
|
$Func: C++ function type (e.g. void(int)), object type not included for method
|
|
$Name: Method name
|
|
$This: Expression for the "this" argument;
|
|
$Arguments: Expressions for arguments separated by ", "
|
|
Default:
|
|
Constructor: new $Type($Arguments)
|
|
Static: $Type::$Name($Arguments)
|
|
Normal: $This->$Name($Arguments)
|
|
Example:
|
|
External constructor: <full-function-name>($Arguments)
|
|
External method: <full-function-name>($This, $Arguments)
|
|
Renamed method: $This-><function-name>($Arguments)
|
|
|
|
GetInvokeTemplate() == L"*":
|
|
This method does not exist in C++
|
|
*/
|
|
virtual const WString& GetInvokeTemplate() = 0;
|
|
virtual const WString& GetClosureTemplate() = 0;
|
|
};
|
|
/*
|
|
Priority:
|
|
1. Use ICpp
|
|
2. Use default
|
|
*/
|
|
virtual ICpp* GetCpp() = 0;
|
|
|
|
virtual IMethodGroupInfo* GetOwnerMethodGroup()=0;
|
|
virtual IPropertyInfo* GetOwnerProperty()=0;
|
|
virtual vint GetParameterCount()=0;
|
|
virtual IParameterInfo* GetParameter(vint index)=0;
|
|
virtual ITypeInfo* GetReturn()=0;
|
|
virtual bool IsStatic()=0;
|
|
virtual void CheckArguments(collections::Array<Value>& arguments)=0;
|
|
virtual Value Invoke(const Value& thisObject, collections::Array<Value>& arguments)=0;
|
|
virtual Value CreateFunctionProxy(const Value& thisObject) = 0;
|
|
};
|
|
|
|
class IMethodGroupInfo : public virtual IMemberInfo, public Description<IMethodGroupInfo>
|
|
{
|
|
public:
|
|
virtual vint GetMethodCount()=0;
|
|
virtual IMethodInfo* GetMethod(vint index)=0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
ITypeDescriptor
|
|
***********************************************************************/
|
|
|
|
enum class TypeDescriptorFlags : vint
|
|
{
|
|
Undefined = 0,
|
|
Object = 1<<0,
|
|
IDescriptable = 1<<1,
|
|
Class = 1<<2,
|
|
Interface = 1<<3,
|
|
Primitive = 1<<4,
|
|
Struct = 1<<5,
|
|
FlagEnum = 1<<6,
|
|
NormalEnum = 1<<7,
|
|
|
|
ClassType = Object | Class,
|
|
InterfaceType = IDescriptable | Interface,
|
|
ReferenceType = ClassType | InterfaceType,
|
|
EnumType = FlagEnum | NormalEnum,
|
|
StructType = Primitive | Struct,
|
|
};
|
|
|
|
inline TypeDescriptorFlags operator&(TypeDescriptorFlags a, TypeDescriptorFlags b)
|
|
{
|
|
return (TypeDescriptorFlags)((vint)a & (vint)b);
|
|
}
|
|
|
|
inline TypeDescriptorFlags operator|(TypeDescriptorFlags a, TypeDescriptorFlags b)
|
|
{
|
|
return (TypeDescriptorFlags)((vint)a | (vint)b);
|
|
}
|
|
|
|
/// <summary>Metadata class for reflectable types.</summary>
|
|
class ITypeDescriptor : public virtual 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
|
|
***********************************************************************/
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
class TypeNotExistsException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
TypeNotExistsException(const WString& name)
|
|
:TypeDescriptorException(L"Cannot find the type \""+name+L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class ConstructorNotExistsException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ConstructorNotExistsException(ITypeDescriptor* type)
|
|
:TypeDescriptorException(L"Cannot find any constructor in type \"" + type->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class MemberNotExistsException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
MemberNotExistsException(const WString& name, ITypeDescriptor* type)
|
|
:TypeDescriptorException(L"Cannot find the member \"" + name + L"\" in type \"" + type->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class PropertyIsNotReadableException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
PropertyIsNotReadableException(IPropertyInfo* propertyInfo)
|
|
:TypeDescriptorException(L"Cannot read value from a property \"" + propertyInfo->GetName() + L"\" that is not readable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class PropertyIsNotWritableException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
PropertyIsNotWritableException(IPropertyInfo* propertyInfo)
|
|
:TypeDescriptorException(L"Cannot write value to a property \"" + propertyInfo->GetName() + L"\" that is not writable in type \"" + propertyInfo->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class ArgumentNullException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ArgumentNullException(const WString& name, const WString& member)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing its member \"" + member + L"\".")
|
|
{
|
|
}
|
|
|
|
ArgumentNullException(const WString& name, IMethodInfo* target)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
|
|
ArgumentNullException(const WString& name, IEventInfo* target)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when accessing event \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
|
|
ArgumentNullException(const WString& name, IPropertyInfo* target)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot be null when invoking property \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class ArgumentTypeMismtatchException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ArgumentTypeMismtatchException(const WString& name, ITypeDescriptor* expected, ITypeDescriptor* actual)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual->GetTypeName() + L"\" to \"" + expected->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
|
|
ArgumentTypeMismtatchException(const WString& name, ITypeInfo* expected, const Value& actual)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" + expected->GetTypeFriendlyName() + L"\".")
|
|
{
|
|
}
|
|
|
|
ArgumentTypeMismtatchException(const WString& name, ITypeDescriptor* type, Value::ValueType valueType, const Value& actual)
|
|
:TypeDescriptorException(L"Argument \"" + name + L"\" cannot convert from \"" + actual.GetTypeFriendlyName() + L"\" to \"" +
|
|
(valueType == Value::SharedPtr ? L"Ptr<" : L"") + type->GetTypeName() + (valueType == Value::SharedPtr ? L">" : valueType == Value::RawPtr ? L"*" : L"")
|
|
+ L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
class ArgumentCountMismtatchException : public TypeDescriptorException
|
|
{
|
|
public:
|
|
ArgumentCountMismtatchException()
|
|
:TypeDescriptorException(L"Argument count does not match the definition.")
|
|
{
|
|
}
|
|
|
|
ArgumentCountMismtatchException(IMethodGroupInfo* target)
|
|
:TypeDescriptorException(L"Argument count does not match the definition when invoking method \"" + target->GetName() + L"\" in type \"" + target->GetOwnerTypeDescriptor()->GetTypeName() + L"\".")
|
|
{
|
|
}
|
|
};
|
|
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PREDEFINED\OBSERVABLELIST.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_TYPES_OBSERVABLELIST
|
|
#define VCZH_REFLECTION_TYPES_OBSERVABLELIST
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace collections
|
|
{
|
|
/// <summary>Base type of observable container which triggers callbacks whenever items are changed.</summary>
|
|
/// <typeparam name="T">Type of elements.</typeparam>
|
|
/// <remarks>
|
|
/// <p>Methods are the same to <see cref="List`2"/>, except that operator[] is readonly.</p>
|
|
/// <p>
|
|
/// When an item is being inserted to the list,
|
|
/// <b>QueryInsert</b> will be called to determine if this item can be inserted,
|
|
/// <b>BeforeInsert</b> will be called before inserting,
|
|
/// <b>AfterInsert</b> will be called after inserting.
|
|
/// </p>
|
|
/// <p>
|
|
/// When an item is being removed from the list,
|
|
/// <b>QueryRemove</b> will be called to determine if this item can be removed,
|
|
/// <b>BeforeRemove</b> will be called before removing,
|
|
/// <b>AfterRemove</b> will be called after removing.
|
|
/// </p>
|
|
/// <p>
|
|
/// When an item is being replaced, it is considered as removing the original item and inserting the new item.
|
|
/// </p>
|
|
/// <p>
|
|
/// After any changing happens, <b>NotifyUpdateInternal</b> is called.
|
|
/// Arguments is exactly the same as <see cref="reflection::description::IValueObservableList::ItemChanged"/>.
|
|
/// </p>
|
|
/// </remarks>
|
|
template<typename T>
|
|
class ObservableListBase : public collections::EnumerableBase<T>
|
|
{
|
|
using K = typename KeyType<T>::Type;
|
|
protected:
|
|
collections::List<T> items;
|
|
|
|
virtual void NotifyUpdateInternal(vint start, vint count, vint newCount)
|
|
{
|
|
}
|
|
|
|
virtual bool QueryInsert(vint index, const T& value)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual void BeforeInsert(vint index, const T& value)
|
|
{
|
|
}
|
|
|
|
virtual void AfterInsert(vint index, const T& value)
|
|
{
|
|
}
|
|
|
|
virtual bool QueryRemove(vint index, const T& value)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual void BeforeRemove(vint index, const T& value)
|
|
{
|
|
}
|
|
|
|
virtual void AfterRemove(vint index, vint count)
|
|
{
|
|
}
|
|
|
|
public:
|
|
collections::IEnumerator<T>* CreateEnumerator()const
|
|
{
|
|
return items.CreateEnumerator();
|
|
}
|
|
|
|
/// <summary>Trigger <b>NotifyUpdateInternal</b> manually.</summary>
|
|
/// <returns>Returns true if arguments are not out of range.</returns>
|
|
/// <param name="start">The index of the first item that are changed.</param>
|
|
/// <param name="count">The number of items that are changed, the default value is 1.</param>
|
|
/// <remarks>
|
|
/// <p>
|
|
/// This is useful when the container is not actually changed, but data in some items are changed.
|
|
/// For example, in an observable list of shared pointers,
|
|
/// properties of elements are changed does not trigger callbacks because it doesn't change pointers in the list.
|
|
/// </p>
|
|
/// <p>
|
|
/// If subscribers need to know about such change, calling this function is an easy way to do it.
|
|
/// </p>
|
|
/// </remarks>
|
|
bool NotifyUpdate(vint start, vint count = 1)
|
|
{
|
|
if (start<0 || start >= items.Count() || count <= 0 || start + count>items.Count())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
NotifyUpdateInternal(start, count, count);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool Contains(const K& item)const
|
|
{
|
|
return items.Contains(item);
|
|
}
|
|
|
|
vint Count()const
|
|
{
|
|
return items.Count();
|
|
}
|
|
|
|
vint Count()
|
|
{
|
|
return items.Count();
|
|
}
|
|
|
|
const T& Get(vint index)const
|
|
{
|
|
return items.Get(index);
|
|
}
|
|
|
|
const T& operator[](vint index)const
|
|
{
|
|
return items.Get(index);
|
|
}
|
|
|
|
vint IndexOf(const K& item)const
|
|
{
|
|
return items.IndexOf(item);
|
|
}
|
|
|
|
vint Add(const T& item)
|
|
{
|
|
return Insert(items.Count(), item);
|
|
}
|
|
|
|
bool Remove(const K& item)
|
|
{
|
|
vint index = items.IndexOf(item);
|
|
if (index == -1) return false;
|
|
return RemoveAt(index);
|
|
}
|
|
|
|
bool RemoveAt(vint index)
|
|
{
|
|
if (0 <= index && index < items.Count() && QueryRemove(index, items[index]))
|
|
{
|
|
BeforeRemove(index, items[index]);
|
|
T item = items[index];
|
|
items.RemoveAt(index);
|
|
AfterRemove(index, 1);
|
|
NotifyUpdateInternal(index, 1, 0);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool RemoveRange(vint index, vint count)
|
|
{
|
|
if (count <= 0) return false;
|
|
if (0 <= index && index<items.Count() && index + count <= items.Count())
|
|
{
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
if (!QueryRemove(index + 1, items[index + i])) return false;
|
|
}
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
BeforeRemove(index + i, items[index + i]);
|
|
}
|
|
items.RemoveRange(index, count);
|
|
AfterRemove(index, count);
|
|
NotifyUpdateInternal(index, count, 0);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Clear()
|
|
{
|
|
vint count = items.Count();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
if (!QueryRemove(i, items[i])) return false;
|
|
}
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
BeforeRemove(i, items[i]);
|
|
}
|
|
items.Clear();
|
|
AfterRemove(0, count);
|
|
NotifyUpdateInternal(0, count, 0);
|
|
return true;
|
|
}
|
|
|
|
vint Insert(vint index, const T& item)
|
|
{
|
|
if (0 <= index && index <= items.Count() && QueryInsert(index, item))
|
|
{
|
|
BeforeInsert(index, item);
|
|
items.Insert(index, item);
|
|
AfterInsert(index, item);
|
|
NotifyUpdateInternal(index, 0, 1);
|
|
return index;
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
bool Set(vint index, const T& item)
|
|
{
|
|
if (0 <= index && index < items.Count())
|
|
{
|
|
if (QueryRemove(index, items[index]) && QueryInsert(index, item))
|
|
{
|
|
BeforeRemove(index, items[index]);
|
|
items.RemoveAt(index);
|
|
AfterRemove(index, 1);
|
|
|
|
BeforeInsert(index, item);
|
|
items.Insert(index, item);
|
|
AfterInsert(index, item);
|
|
|
|
NotifyUpdateInternal(index, 1, 1);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/// <summary>An observable container that maintain an implementation of <see cref="reflection::description::IValueObservableList"/>.</summary>
|
|
/// <typeparam name="T">Type of elements.</typeparam>
|
|
template<typename T>
|
|
class ObservableList : public ObservableListBase<T>
|
|
{
|
|
protected:
|
|
void NotifyUpdateInternal(vint start, vint count, vint newCount) override;
|
|
|
|
public:
|
|
};
|
|
|
|
namespace randomaccess_internal
|
|
{
|
|
template<typename T>
|
|
struct RandomAccessable<ObservableListBase<T>>
|
|
{
|
|
static const bool CanRead = true;
|
|
static const bool CanResize = false;
|
|
};
|
|
|
|
template<typename T>
|
|
struct RandomAccessable<ObservableList<T>>
|
|
{
|
|
static const bool CanRead = true;
|
|
static const bool CanResize = false;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\PREDEFINED\TYPEDVALUESERIALIZERPROVIDER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_TYPES_TYPEDVALUESERIALIZERPROVIDER
|
|
#define VCZH_REFLECTION_TYPES_TYPEDVALUESERIALIZERPROVIDER
|
|
|
|
#include <limits.h>
|
|
#include <float.h>
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Constants
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypedValueSerializerMinMax;
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vint8_t>
|
|
{
|
|
static constexpr vint8_t Min = _I8_MIN;
|
|
static constexpr vint8_t Max = _I8_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vint16_t>
|
|
{
|
|
static constexpr vint16_t Min = _I16_MIN;
|
|
static constexpr vint16_t Max = _I16_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vint32_t>
|
|
{
|
|
static constexpr vint32_t Min = _I32_MIN;
|
|
static constexpr vint32_t Max = _I32_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vint64_t>
|
|
{
|
|
static constexpr vint64_t Min = _I64_MIN;
|
|
static constexpr vint64_t Max = _I64_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vuint8_t>
|
|
{
|
|
static constexpr vuint8_t Min = 0;
|
|
static constexpr vuint8_t Max = _UI8_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vuint16_t>
|
|
{
|
|
static constexpr vuint16_t Min = 0;
|
|
static constexpr vuint16_t Max = _UI16_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vuint32_t>
|
|
{
|
|
static constexpr vuint32_t Min = 0;
|
|
static constexpr vuint32_t Max = _UI32_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<vuint64_t>
|
|
{
|
|
static constexpr vuint64_t Min = 0;
|
|
static constexpr vuint64_t Max = _UI64_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<float>
|
|
{
|
|
static constexpr float Min = (float)-FLT_MAX;
|
|
static constexpr float Max = (float)FLT_MAX;
|
|
};
|
|
|
|
template<>
|
|
struct TypedValueSerializerMinMax<double>
|
|
{
|
|
static constexpr double Min = (double)-DBL_MAX;
|
|
static constexpr double Max = (double)DBL_MAX;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Signed Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypedValueSerializerProvider_Signed
|
|
{
|
|
static T GetDefaultValue()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static bool Serialize(const T& input, WString& output)
|
|
{
|
|
output = i64tow(input);
|
|
return true;
|
|
}
|
|
|
|
static bool Deserialize(const WString& input, T& output)
|
|
{
|
|
constexpr T MinValue = TypedValueSerializerMinMax<T>::Min;
|
|
constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
|
|
bool success = false;
|
|
vint64_t result = wtoi64_test(input, success);
|
|
if (!success) return false;
|
|
if (result < MinValue || result > MaxValue) return false;
|
|
output = (T)result;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Unsigned Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypedValueSerializerProvider_Unsigned
|
|
{
|
|
static T GetDefaultValue()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static bool Serialize(const T& input, WString& output)
|
|
{
|
|
output = u64tow(input);
|
|
return true;
|
|
}
|
|
|
|
static bool Deserialize(const WString& input, T& output)
|
|
{
|
|
constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
|
|
bool success = false;
|
|
vuint64_t result = wtou64_test(input, success);
|
|
if (!success) return false;
|
|
if (result > MaxValue) return false;
|
|
output = (T)result;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Floating Point Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypedValueSerializerProvider_FloatingPoint
|
|
{
|
|
static T GetDefaultValue()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static bool Serialize(const T& input, WString& output)
|
|
{
|
|
output = ftow(input);
|
|
if (output == L"-0") output = L"0";
|
|
return true;
|
|
}
|
|
|
|
static bool Deserialize(const WString& input, T& output)
|
|
{
|
|
constexpr T MinValue = TypedValueSerializerMinMax<T>::Min;
|
|
constexpr T MaxValue = TypedValueSerializerMinMax<T>::Max;
|
|
bool success = false;
|
|
double result = wtof_test(input, success);
|
|
if (!success) return false;
|
|
if (result < MinValue || result > MaxValue) return false;
|
|
output = (T)result;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Serializable Types
|
|
***********************************************************************/
|
|
|
|
#define DEFINE_SIGNED_TVSP(TYPENAME)\
|
|
template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_Signed<TYPENAME> {};\
|
|
|
|
DEFINE_SIGNED_TVSP(vint8_t)
|
|
DEFINE_SIGNED_TVSP(vint16_t)
|
|
DEFINE_SIGNED_TVSP(vint32_t)
|
|
DEFINE_SIGNED_TVSP(vint64_t)
|
|
#undef DEFINE_SIGNED_TVSP
|
|
|
|
#define DEFINE_UNSIGNED_TVSP(TYPENAME)\
|
|
template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_Unsigned<TYPENAME> {};\
|
|
|
|
DEFINE_UNSIGNED_TVSP(vuint8_t)
|
|
DEFINE_UNSIGNED_TVSP(vuint16_t)
|
|
DEFINE_UNSIGNED_TVSP(vuint32_t)
|
|
DEFINE_UNSIGNED_TVSP(vuint64_t)
|
|
#undef DEFINE_UNSIGNED_TVSP
|
|
|
|
#define DEFINE_FLOAT_TVSP(TYPENAME)\
|
|
template<> struct TypedValueSerializerProvider<TYPENAME> : TypedValueSerializerProvider_FloatingPoint<TYPENAME> {};\
|
|
|
|
DEFINE_FLOAT_TVSP(float)
|
|
DEFINE_FLOAT_TVSP(double)
|
|
#undef DEFINE_FLOAT_TVSP
|
|
|
|
#define DEFINE_TVSP(TYPENAME)\
|
|
template<>\
|
|
struct TypedValueSerializerProvider<TYPENAME>\
|
|
{\
|
|
static TYPENAME GetDefaultValue();\
|
|
static bool Serialize(const TYPENAME& input, WString& output);\
|
|
static bool Deserialize(const WString& input, TYPENAME& output);\
|
|
};\
|
|
|
|
DEFINE_TVSP(bool)
|
|
DEFINE_TVSP(wchar_t)
|
|
DEFINE_TVSP(WString)
|
|
DEFINE_TVSP(Locale)
|
|
DEFINE_TVSP(DateTime)
|
|
|
|
#undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\PREDEFINED\PREDEFINEDTYPES.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_TYPES_PREDEFINEDTYPES
|
|
#define VCZH_REFLECTION_TYPES_PREDEFINEDTYPES
|
|
|
|
#include <math.h>
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
struct VoidValue {};
|
|
|
|
/***********************************************************************
|
|
Collections
|
|
***********************************************************************/
|
|
|
|
/// <summary>The reflectable version of <see cref="collections::IEnumerator`1"/>.</summary>
|
|
class IValueEnumerator : public virtual IDescriptable, public Description<IValueEnumerator>
|
|
{
|
|
public:
|
|
/// <summary>Get the reference to the current value in the enumerator.</summary>
|
|
/// <returns>The current value.</returns>
|
|
/// <remarks><see cref="Next"/> needs to be called to make the first value available.</remarks>
|
|
virtual Value GetCurrent() = 0;
|
|
|
|
/// <summary>Get the position of the current value in the enumerator.</summary>
|
|
/// <returns>The position of the current value.</returns>
|
|
virtual vint GetIndex() = 0;
|
|
|
|
/// <summary>Prepare for the next value.</summary>
|
|
/// <returns>Returns false if there is no more value.</returns>
|
|
virtual bool Next() = 0;
|
|
};
|
|
|
|
/// <summary>The reflectable version of <see cref="collections::IEnumerable`1"/>.</summary>
|
|
/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from an enumerable.</remarks>
|
|
/// <example><
|
|
/// {
|
|
/// return Ptr(new MyClass(i));
|
|
/// });
|
|
///
|
|
/// Value boxed = BoxParameter(cs);
|
|
/// {
|
|
/// auto enumerable = UnboxValue<Ptr<IValueEnumerable>>(boxed);
|
|
/// auto enumerator = enumerable->CreateEnumerator();
|
|
/// while (enumerator->Next())
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<Ptr<MyClass>>(enumerator->GetCurrent())->data) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
/// {
|
|
/// auto enumerator = boxed.Invoke(L"CreateEnumerator");
|
|
/// while (UnboxValue<bool>(enumerator.Invoke(L"Next")))
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<vint>(enumerator.GetProperty(L"Current").GetProperty(L"data"))) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
class IValueEnumerable : public virtual IDescriptable, public Description<IValueEnumerable>
|
|
{
|
|
public:
|
|
/// <summary>
|
|
/// Create an enumerator. <see cref="IValueEnumerator::Next"/> should be called before reading the first value.
|
|
/// </summary>
|
|
/// <returns>The enumerator.</returns>
|
|
virtual Ptr<IValueEnumerator> CreateEnumerator() = 0;
|
|
|
|
/// <summary>Get the underlying collection object, which is boxed to be this interface.</summary>
|
|
/// <returns>The underlying collection object, could be nullptr.</returns>
|
|
virtual const Object* GetCollectionObject() { return nullptr; }
|
|
|
|
/// <summary>Create an enumerable from another lazy list.</summary>
|
|
/// <returns>The created enumerable.</returns>
|
|
/// <param name="values">The lazy list to wrap.</param>
|
|
static Ptr<IValueEnumerable> Create(collections::LazyList<Value> values);
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of readonly
|
|
/// <see cref="collections::Array`2"/>,
|
|
/// <see cref="collections::List`2"/> or
|
|
/// <see cref="collections::SortedList`2"/>
|
|
/// <see cref="collections::ObservableListBase`2"/>
|
|
/// <see cref="collections::ObservableList`2"/>
|
|
/// </summary>
|
|
class IValueReadonlyList : public virtual IValueEnumerable, public Description<IValueReadonlyList>
|
|
{
|
|
public:
|
|
/// <summary>Get the number of elements in the container.</summary>
|
|
/// <returns>The number of elements.</returns>
|
|
virtual vint GetCount() = 0;
|
|
|
|
/// <summary>Get the reference to the specified element.</summary>
|
|
/// <returns>The reference to the specified element. It will crash when the index is out of range.</returns>
|
|
/// <param name="index">The index of the element.</param>
|
|
virtual Value Get(vint index) = 0;
|
|
|
|
/// <summary>Test does the list contain a value or not.</summary>
|
|
/// <returns>Returns true if the list contains the specified value.</returns>
|
|
/// <param name="value">The value to test.</param>
|
|
virtual bool Contains(const Value& value) = 0;
|
|
|
|
/// <summary>Get the position of a value in this list.</summary>
|
|
/// <returns>Returns the position of first element that equals to the specified value. Returns -1 if failed to find.</returns>
|
|
/// <param name="value">The value to find.</param>
|
|
virtual vint IndexOf(const Value& value) = 0;
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of writable
|
|
/// <see cref="collections::Array`2"/>
|
|
/// </summary>
|
|
/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a container.</remarks>
|
|
class IValueArray : public virtual IValueReadonlyList, public Description<IValueArray>
|
|
{
|
|
public:
|
|
/// <summary>Replace an element in the specified position.</summary>
|
|
/// <returns>Returns true if this operation succeeded. It will crash when the index is out of range</returns>
|
|
/// <param name="index">The position of the element to replace.</param>
|
|
/// <param name="value">The new value to replace.</param>
|
|
virtual void Set(vint index, const Value& value) = 0;
|
|
|
|
/// <summary>Append a value at the end of the list.</summary>
|
|
/// <returns>The index of the added item.</returns>
|
|
/// <param name="value">The value to add.</param>
|
|
virtual void Resize(vint size) = 0;
|
|
|
|
/// <summary>Create an empty array.</summary>
|
|
/// <returns>The created list.</returns>
|
|
static Ptr<IValueArray> Create();
|
|
|
|
/// <summary>Create an array with elements copied from another readonly list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueArray> Create(Ptr<IValueReadonlyList> values);
|
|
|
|
/// <summary>Create an array with elements copied from another lazy list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueArray> Create(collections::LazyList<Value> values);
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of writable
|
|
/// <see cref="collections::Array`2"/> or
|
|
/// <see cref="collections::List`2"/> or
|
|
/// <see cref="collections::ObservableListBase`2"/>
|
|
/// </summary>
|
|
/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a container.</remarks>
|
|
/// <example><
|
|
/// {
|
|
/// return Ptr(new MyClass(i));
|
|
/// })
|
|
/// );
|
|
///
|
|
/// Value boxed = BoxParameter(cs);
|
|
/// {
|
|
/// auto list = UnboxValue<Ptr<IValueList>>(boxed);
|
|
/// for (vint i = 0; i < list->GetCount(); i++)
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<Ptr<MyClass>>(list->Get(i))->data) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
///
|
|
/// for (vint i = 1; i <= 5; i++)
|
|
/// {
|
|
/// cs.RemoveAt(i);
|
|
/// }
|
|
///
|
|
/// {
|
|
/// for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
class IValueList : public virtual IValueReadonlyList, public Description<IValueList>
|
|
{
|
|
public:
|
|
/// <summary>Replace an element in the specified position.</summary>
|
|
/// <returns>Returns true if this operation succeeded. It will crash when the index is out of range</returns>
|
|
/// <param name="index">The position of the element to replace.</param>
|
|
/// <param name="value">The new value to replace.</param>
|
|
virtual void Set(vint index, const Value& value) = 0;
|
|
|
|
/// <summary>Append a value at the end of the list.</summary>
|
|
/// <returns>The index of the added item.</returns>
|
|
/// <param name="value">The value to add.</param>
|
|
virtual vint Add(const Value& value) = 0;
|
|
|
|
/// <summary>Insert a value at the specified position.</summary>
|
|
/// <returns>The index of the added item. It will crash if the index is out of range</returns>
|
|
/// <param name="index">The position to insert the value.</param>
|
|
/// <param name="value">The value to add.</param>
|
|
virtual vint Insert(vint index, const Value& value) = 0;
|
|
|
|
/// <summary>Remove an element from the list. If multiple elements equal to the specified value, only the first one will be removed.</summary>
|
|
/// <returns>Returns true if the element is removed.</returns>
|
|
/// <param name="value">The item to remove.</param>
|
|
virtual bool Remove(const Value& value) = 0;
|
|
|
|
/// <summary>Remove an element at a specified position.</summary>
|
|
/// <returns>Returns true if the element is removed. It will crash when the index is out of range.</returns>
|
|
/// <param name="index">The index of the element to remove.</param>
|
|
virtual bool RemoveAt(vint index) = 0;
|
|
|
|
/// <summary>Remove all elements.</summary>
|
|
virtual void Clear() = 0;
|
|
|
|
/// <summary>Create an empty list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
static Ptr<IValueList> Create();
|
|
|
|
/// <summary>Create a list with elements copied from another readonly list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueList> Create(Ptr<IValueReadonlyList> values);
|
|
|
|
/// <summary>Create a list with elements copied from another lazy list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueList> Create(collections::LazyList<Value> values);
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of list container which triggers an event whenever items are changed.
|
|
/// </summary>
|
|
/// <example><
|
|
/// {
|
|
/// return Ptr(new MyClass(i));
|
|
/// })
|
|
/// );
|
|
///
|
|
/// Value boxed = BoxParameter(cs);
|
|
/// auto list = UnboxValue<Ptr<IValueObservableList>>(boxed);
|
|
/// {
|
|
/// for (vint i = 0; i < list->GetCount(); i++)
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<Ptr<MyClass>>(list->Get(i))->data) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
///
|
|
/// {
|
|
/// using CallbackType = Func<void(vint, vint, vint)>;
|
|
/// CallbackType callbackFunction = [](vint index, vint oldCount, vint newCount)
|
|
/// {
|
|
/// Console::WriteLine(L"ItemChanged(" + itow(index) + L", " + itow(oldCount) + L", " + itow(newCount) + L");");
|
|
/// };
|
|
///
|
|
/// auto handler = boxed.AttachEvent(L"ItemChanged", BoxParameter(callbackFunction));
|
|
/// for (vint i = 1; i <= 5; i++)
|
|
/// {
|
|
/// cs.RemoveAt(i);
|
|
/// }
|
|
/// boxed.DetachEvent(L"ItemChanged", handler);
|
|
/// }
|
|
///
|
|
/// {
|
|
/// for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
|
|
/// {
|
|
/// Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
class IValueObservableList : public virtual IValueList, public Description<IValueObservableList>
|
|
{
|
|
typedef void ItemChangedProc(vint index, vint oldCount, vint newCount);
|
|
public:
|
|
/// <summary>
|
|
/// <p>Event that is triggered whenever items are changed.</p>
|
|
/// <p>The first argument is the index of the first item that is changed.</p>
|
|
/// <p>The second argument is the number of original items that are replaced by new items.</p>
|
|
/// <p>The third argument is the number of new items that replace original items.</p>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <p>If an item is changed, oldCount and newCount are both 1.</p>
|
|
/// <p>If several items are removed from the list, newCount is 0.</p>
|
|
/// <p>If several items are inserted to the list, oldCount is 0.</p>
|
|
/// <p>This event is triggered when the updating is done, original items are not possible to access at the moment.</p>
|
|
/// </remarks>
|
|
Event<ItemChangedProc> ItemChanged;
|
|
|
|
/// <summary>Create an empty list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
static Ptr<IValueObservableList> Create();
|
|
|
|
/// <summary>Create a list with elements copied from another readonly list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueObservableList> Create(Ptr<IValueReadonlyList> values);
|
|
|
|
/// <summary>Create a list with elements copied from another lazy list.</summary>
|
|
/// <returns>The created list.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueObservableList> Create(collections::LazyList<Value> values);
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of readonly <see cref="collections::Dictionary`4"/>.
|
|
/// </summary>
|
|
class IValueReadonlyDictionary : public virtual IDescriptable, public Description<IValueReadonlyDictionary>
|
|
{
|
|
public:
|
|
/// <summary>Get all keys.</summary>
|
|
/// <returns>All keys.</returns>
|
|
virtual Ptr<IValueReadonlyList> GetKeys() = 0;
|
|
|
|
/// <summary>Get all values.</summary>
|
|
/// <returns>All values.</returns>
|
|
virtual Ptr<IValueReadonlyList> GetValues() = 0;
|
|
|
|
/// <summary>Get the number of keys.</summary>
|
|
/// <returns>The number of keys. It is also the number of values.</returns>
|
|
virtual vint GetCount() = 0;
|
|
|
|
/// <summary>Get the value associated to a specified key.</summary>
|
|
/// <returns>The reference to the value. It will crash if the key does not exist.</returns>
|
|
/// <param name="key">The key to find.</param>
|
|
virtual Value Get(const Value& key) = 0;
|
|
|
|
/// <summary>Get the underlying collection object, which is boxed to be this interface.</summary>
|
|
/// <returns>The underlying collection object, could be nullptr.</returns>
|
|
virtual const Object* GetCollectionObject() { return nullptr; }
|
|
};
|
|
|
|
/// <summary>
|
|
/// The reflectable version of writable <see cref="collections::Dictionary`4"/>.
|
|
/// </summary>
|
|
/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a dictionary.</remarks>
|
|
/// <example>< -> Pair<vint, Ptr<MyClass>>
|
|
/// {
|
|
/// return { i, Ptr(new MyClass(i * i)) };
|
|
/// })
|
|
/// );
|
|
///
|
|
/// Value boxed = BoxParameter(cs);
|
|
/// {
|
|
/// auto dictionary = UnboxValue<Ptr<IValueDictionary>>(boxed);
|
|
/// for (vint i = 0; i < dictionary->GetCount(); i++)
|
|
/// {
|
|
/// Value key = dictionary->GetKeys()->Get(i);
|
|
/// Console::Write(itow(UnboxValue<Ptr<MyClass>>(dictionary->Get(key))->data) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
///
|
|
/// for (vint i = 1; i <= 5; i++)
|
|
/// {
|
|
/// cs.Remove(i * 2);
|
|
/// }
|
|
///
|
|
/// {
|
|
/// for (vint i = 0; i < UnboxValue<vint>(boxed.GetProperty(L"Count")); i++)
|
|
/// {
|
|
/// Value key = boxed.GetProperty(L"Keys").Invoke(L"Get", (Value_xs(), i));
|
|
/// Console::Write(itow(UnboxValue<vint>(boxed.Invoke(L"Get", (Value_xs(), key)).GetProperty(L"data"))) + L" ");
|
|
/// }
|
|
/// Console::WriteLine(L"");
|
|
/// }
|
|
/// }
|
|
/// DestroyGlobalTypeManager();
|
|
/// }
|
|
/// ]]></example>
|
|
class IValueDictionary : public virtual IValueReadonlyDictionary, public Description<IValueDictionary>
|
|
{
|
|
public:
|
|
/// <summary>Replace the value associated to a specified key.</summary>
|
|
/// <returns>Returns true if the value is replaced.</returns>
|
|
/// <param name="key">The key to find. If the key does not exist, it will be added to the dictionary.</param>
|
|
/// <param name="value">The associated value to replace.</param>
|
|
virtual void Set(const Value& key, const Value& value) = 0;
|
|
|
|
/// <summary>Remove a key with the associated value.</summary>
|
|
/// <returns>Returns true if the key and the value is removed.</returns>
|
|
/// <param name="key">The key to find.</param>
|
|
virtual bool Remove(const Value& key) = 0;
|
|
|
|
/// <summary>Remove all elements.</summary>
|
|
virtual void Clear() = 0;
|
|
|
|
/// <summary>Create an empty dictionary.</summary>
|
|
/// <returns>The created dictionary.</returns>
|
|
static Ptr<IValueDictionary> Create();
|
|
|
|
/// <summary>Create a dictionary with elements copied from another readonly dictionary.</summary>
|
|
/// <returns>The created dictionary.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueDictionary> Create(Ptr<IValueReadonlyDictionary> values);
|
|
|
|
/// <summary>Create a dictionary with elements copied from another lazy list.</summary>
|
|
/// <returns>The created dictionary.</returns>
|
|
/// <param name="values">Elements to copy.</param>
|
|
static Ptr<IValueDictionary> Create(collections::LazyList<collections::Pair<Value, Value>> values);
|
|
};
|
|
|
|
/***********************************************************************
|
|
Interface Implementation Proxy
|
|
***********************************************************************/
|
|
|
|
class IValueInterfaceProxy : public virtual IDescriptable, public Description<IValueInterfaceProxy>
|
|
{
|
|
public:
|
|
virtual Value Invoke(IMethodInfo* methodInfo, Ptr<IValueReadonlyList> arguments) = 0;
|
|
};
|
|
|
|
/// <summary>A reflectable version of <see cref="Func`1"/>.</summary>
|
|
/// <remarks><see cref="BoxParameter`1"/> will create a <see cref="Value"/> storing a shared pointer to an instance of this interface from a function.</remarks>
|
|
class IValueFunctionProxy : public virtual IDescriptable, public Description<IValueFunctionProxy>
|
|
{
|
|
public:
|
|
/// <summary>Call the function.</summary>
|
|
/// <returns>Return value from the function.</returns>
|
|
/// <param name="arguments">Arguments to call the function.</param>
|
|
virtual Value Invoke(Ptr<IValueReadonlyList> arguments) = 0;
|
|
};
|
|
|
|
/// <summary>A reflectable subscription, usually created by the <b>bind</b> expression in Workflow script.</summary>
|
|
class IValueSubscription : public virtual IDescriptable, public Description<IValueSubscription>
|
|
{
|
|
typedef void ValueChangedProc(const Value& newValue);
|
|
public:
|
|
/// <summary>Event that triggered when the binding source is changed.</summary>
|
|
/// <remarks>The first argument is the new value of the binding source.</remarks>
|
|
Event<ValueChangedProc> ValueChanged;
|
|
|
|
/// <summary>Start the subscription.</summary>
|
|
/// <returns>Returns true if this operation succeeded.</summary>
|
|
virtual bool Open() = 0;
|
|
|
|
/// <summary>Manually trigger the event.</summary>
|
|
/// <returns>Returns true if this operation succeeded.</summary>
|
|
virtual bool Update() = 0;
|
|
|
|
/// <summary>Stop the subscription.</summary>
|
|
/// <returns>Returns true if this operation succeeded.</summary>
|
|
virtual bool Close() = 0;
|
|
};
|
|
|
|
/***********************************************************************
|
|
Interface Implementation Proxy (Implement)
|
|
***********************************************************************/
|
|
|
|
class ValueInterfaceRoot : public virtual IDescriptable
|
|
{
|
|
protected:
|
|
Ptr<IValueInterfaceProxy> proxy;
|
|
|
|
void SetProxy(Ptr<IValueInterfaceProxy> value)
|
|
{
|
|
proxy = value;
|
|
}
|
|
public:
|
|
Ptr<IValueInterfaceProxy> GetProxy()
|
|
{
|
|
return proxy;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueInterfaceProxy
|
|
{
|
|
};
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4250)
|
|
template<typename TInterface, typename ...TBaseInterfaces>
|
|
class ValueInterfaceImpl : public virtual ValueInterfaceRoot, public virtual TInterface, public ValueInterfaceProxy<TBaseInterfaces>...
|
|
{
|
|
public:
|
|
~ValueInterfaceImpl()
|
|
{
|
|
FinalizeAggregation();
|
|
}
|
|
};
|
|
#pragma warning(pop)
|
|
|
|
/***********************************************************************
|
|
Runtime Exception
|
|
***********************************************************************/
|
|
|
|
class IValueCallStack : public virtual IDescriptable, public Description<IValueCallStack>
|
|
{
|
|
public:
|
|
virtual Ptr<IValueReadonlyDictionary> GetLocalVariables() = 0;
|
|
virtual Ptr<IValueReadonlyDictionary> GetLocalArguments() = 0;
|
|
virtual Ptr<IValueReadonlyDictionary> GetCapturedVariables() = 0;
|
|
virtual Ptr<IValueReadonlyDictionary> GetGlobalVariables() = 0;
|
|
virtual WString GetFunctionName() = 0;
|
|
virtual WString GetSourceCodeBeforeCodegen() = 0;
|
|
virtual WString GetSourceCodeAfterCodegen() = 0;
|
|
virtual vint GetRowBeforeCodegen() = 0;
|
|
virtual vint GetRowAfterCodegen() = 0;
|
|
};
|
|
|
|
class IValueException : public virtual IDescriptable, public Description<IValueException>
|
|
{
|
|
public:
|
|
#pragma push_macro("GetMessage")
|
|
#if defined GetMessage
|
|
#undef GetMessage
|
|
#endif
|
|
virtual WString GetMessage() = 0;
|
|
#pragma pop_macro("GetMessage")
|
|
virtual bool GetFatal() = 0;
|
|
virtual Ptr<IValueReadonlyList> GetCallStack() = 0;
|
|
|
|
static Ptr<IValueException> Create(const WString& message);
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\METADATA\METADATA.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_METADATA_METADATA
|
|
#define VCZH_REFLECTION_METADATA_METADATA
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
template<typename T>
|
|
struct TypeInfoRetriver;
|
|
|
|
/// <summary>
|
|
/// A reference holder to an unboxed object.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the unboxed object.</typeparam>
|
|
template<typename T>
|
|
struct Unboxed
|
|
{
|
|
private:
|
|
T* object;
|
|
bool owned;
|
|
|
|
public:
|
|
Unboxed(T* _object, bool _owned) : object(_object), owned(_owned) {}
|
|
Unboxed(Unboxed<T>&& unboxed) : object(unboxed.object), owned(unboxed.owned) { unboxed.object = nullptr; }
|
|
~Unboxed() { if (object && owned) { delete object; } }
|
|
|
|
Unboxed() = delete;
|
|
Unboxed(const Unboxed<T>&&) = delete;
|
|
Unboxed<T>& operator=(const Unboxed<T>&) = delete;
|
|
Unboxed<T>& operator=(Unboxed<T>&&) = delete;
|
|
|
|
/// <summary>
|
|
/// Get the reference of the unboxed object.
|
|
/// It is recommended only to use this reference when the <see cref="Unboxe`1"/> is still alive.
|
|
/// </summary>
|
|
/// <returns>The unboxed object.</returns>
|
|
T& Ref() const { CHECK_ERROR(object, L"vl::reflection::description::Unboxed<T>::Ref()#The object has been moved away."); return *object; }
|
|
|
|
/// <summary>
|
|
/// Test if the unboxed object is owned.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
bool IsOwned() const
|
|
{
|
|
return owned;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor = nullptr);
|
|
|
|
template<typename T>
|
|
T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor = nullptr, const WString& valueName = WString::Unmanaged(L"value"));
|
|
|
|
template<typename T>
|
|
Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor = nullptr);
|
|
|
|
template<typename T>
|
|
Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor = nullptr, const WString& valueName = WString::Unmanaged(L"value"));
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
TypeInfo
|
|
***********************************************************************/
|
|
|
|
#define DECL_TYPE_INFO(TYPENAME) template<>struct TypeInfo<TYPENAME>{ static const TypeInfoContent content; };
|
|
#define IMPL_VL_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::VlppType };
|
|
#define IMPL_CPP_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #TYPENAME, nullptr, TypeInfoContent::CppType };
|
|
#define IMPL_TYPE_INFO_RENAME(TYPENAME, EXPECTEDNAME) const TypeInfoContent TypeInfo<TYPENAME>::content = { L ## #EXPECTEDNAME, L ## #TYPENAME, TypeInfoContent::Renamed };
|
|
|
|
struct TypeInfoContent
|
|
{
|
|
enum TypeInfoCppName
|
|
{
|
|
VlppType, // vl::<type-name>
|
|
CppType, // <type-name>
|
|
Renamed, // CppFullTypeName
|
|
};
|
|
|
|
const wchar_t* typeName;
|
|
const wchar_t* cppFullTypeName;
|
|
TypeInfoCppName cppName;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeInfo;
|
|
|
|
/// <summary>Get a registered type given a C++ type.</summary>
|
|
/// <returns>Returns the metadata class for this registered type.</returns>
|
|
/// <typeparam name="T">The C++ type to get the registered type.</typeparam>
|
|
/// <remarks>
|
|
/// Returning null means the type registration is declared but the type manager has not started.
|
|
/// Failing to compile means that the type registration is not declared.
|
|
/// See <see cref="Description`1"/> about how to register a type.
|
|
/// </remarks>
|
|
template<typename T>
|
|
ITypeDescriptor* GetTypeDescriptor()
|
|
{
|
|
static vint typeVersion = -1;
|
|
static ITypeDescriptor* cached = nullptr;
|
|
if (auto tm = GetGlobalTypeManager())
|
|
{
|
|
auto currentVersion = tm->GetTypeVersion();
|
|
if (typeVersion != currentVersion)
|
|
{
|
|
cached = GetTypeDescriptor(TypeInfo<T>::content.typeName);
|
|
}
|
|
return cached;
|
|
}
|
|
else
|
|
{
|
|
typeVersion = -1;
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
TypeInfoImp
|
|
***********************************************************************/
|
|
|
|
class TypeDescriptorTypeInfo : public Object, public ITypeInfo
|
|
{
|
|
protected:
|
|
ITypeDescriptor* typeDescriptor;
|
|
TypeInfoHint hint;
|
|
|
|
public:
|
|
TypeDescriptorTypeInfo(ITypeDescriptor* _typeDescriptor, TypeInfoHint _hint);
|
|
~TypeDescriptorTypeInfo();
|
|
|
|
Decorator GetDecorator()override;
|
|
TypeInfoHint GetHint()override;
|
|
ITypeInfo* GetElementType()override;
|
|
ITypeDescriptor* GetTypeDescriptor()override;
|
|
vint GetGenericArgumentCount()override;
|
|
ITypeInfo* GetGenericArgument(vint index)override;
|
|
WString GetTypeFriendlyName()override;
|
|
};
|
|
|
|
class DecoratedTypeInfo : public Object, public ITypeInfo
|
|
{
|
|
protected:
|
|
Ptr<ITypeInfo> elementType;
|
|
|
|
public:
|
|
DecoratedTypeInfo(Ptr<ITypeInfo> _elementType);
|
|
~DecoratedTypeInfo();
|
|
|
|
TypeInfoHint GetHint()override;
|
|
ITypeInfo* GetElementType()override;
|
|
ITypeDescriptor* GetTypeDescriptor()override;
|
|
vint GetGenericArgumentCount()override;
|
|
ITypeInfo* GetGenericArgument(vint index)override;
|
|
};
|
|
|
|
class RawPtrTypeInfo : public DecoratedTypeInfo
|
|
{
|
|
public:
|
|
RawPtrTypeInfo(Ptr<ITypeInfo> _elementType);
|
|
~RawPtrTypeInfo();
|
|
|
|
Decorator GetDecorator()override;
|
|
WString GetTypeFriendlyName()override;
|
|
};
|
|
|
|
class SharedPtrTypeInfo : public DecoratedTypeInfo
|
|
{
|
|
public:
|
|
SharedPtrTypeInfo(Ptr<ITypeInfo> _elementType);
|
|
~SharedPtrTypeInfo();
|
|
|
|
Decorator GetDecorator()override;
|
|
WString GetTypeFriendlyName()override;
|
|
};
|
|
|
|
class NullableTypeInfo : public DecoratedTypeInfo
|
|
{
|
|
public:
|
|
NullableTypeInfo(Ptr<ITypeInfo> _elementType);
|
|
~NullableTypeInfo();
|
|
|
|
Decorator GetDecorator()override;
|
|
WString GetTypeFriendlyName()override;
|
|
};
|
|
|
|
class GenericTypeInfo : public DecoratedTypeInfo
|
|
{
|
|
protected:
|
|
collections::List<Ptr<ITypeInfo>> genericArguments;
|
|
|
|
public:
|
|
GenericTypeInfo(Ptr<ITypeInfo> _elementType);
|
|
~GenericTypeInfo();
|
|
|
|
Decorator GetDecorator()override;
|
|
vint GetGenericArgumentCount()override;
|
|
ITypeInfo* GetGenericArgument(vint index)override;
|
|
WString GetTypeFriendlyName()override;
|
|
|
|
void AddGenericArgument(Ptr<ITypeInfo> value);
|
|
};
|
|
|
|
#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<IValueReadonlyList> arguments)=0;
|
|
virtual Ptr<ITypeInfo> GetHandlerTypeInternal()=0;
|
|
public:
|
|
EventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name);
|
|
~EventInfoImpl();
|
|
|
|
ITypeDescriptor* GetOwnerTypeDescriptor()override;
|
|
const WString& GetName()override;
|
|
ITypeInfo* GetHandlerType()override;
|
|
vint GetObservingPropertyCount()override;
|
|
IPropertyInfo* GetObservingProperty(vint index)override;
|
|
Ptr<IEventHandler> Attach(const Value& thisObject, Ptr<IValueFunctionProxy> handler)override;
|
|
bool Detach(const Value& thisObject, Ptr<IEventHandler> handler)override;
|
|
void Invoke(const Value& thisObject, Ptr<IValueReadonlyList> arguments)override;
|
|
};
|
|
|
|
/***********************************************************************
|
|
TypeDescriptorImpl
|
|
***********************************************************************/
|
|
|
|
class PropertyInfoImpl : public 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
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
/***********************************************************************
|
|
CustomFieldInfoImpl
|
|
***********************************************************************/
|
|
|
|
template<typename TClass, typename TField>
|
|
class CustomFieldInfoImpl : public FieldInfoImpl
|
|
{
|
|
protected:
|
|
TField TClass::* fieldRef;
|
|
|
|
Value GetValueInternal(const Value& thisObject)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject);
|
|
if (object)
|
|
{
|
|
return BoxParameter(object->*fieldRef, GetReturn()->GetTypeDescriptor());
|
|
}
|
|
return Value();
|
|
}
|
|
|
|
void SetValueInternal(Value& thisObject, const Value& newValue)override
|
|
{
|
|
if constexpr (std::is_copy_assignable_v<TField>)
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject);
|
|
if (object)
|
|
{
|
|
auto result = UnboxParameter<TField>(newValue, GetReturn()->GetTypeDescriptor(), L"newValue");
|
|
object->*fieldRef = result.Ref();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw PropertyIsNotWritableException(this);
|
|
}
|
|
}
|
|
public:
|
|
CustomFieldInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, TField TClass::* _fieldRef)
|
|
:FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
|
|
, fieldRef(_fieldRef)
|
|
{
|
|
}
|
|
|
|
IPropertyInfo::ICpp* GetCpp()override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
bool IsWritable()override
|
|
{
|
|
return std::is_copy_assignable_v<TField>;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
PrimitiveTypeDescriptor
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
template<typename T>
|
|
class SerializableValueType : public Object, public virtual IValueType
|
|
{
|
|
public:
|
|
Value CreateDefault()override
|
|
{
|
|
return BoxValue<T>(TypedValueSerializerProvider<T>::GetDefaultValue());
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class SerializableType : public Object, public virtual ISerializableType
|
|
{
|
|
public:
|
|
bool Serialize(const Value& input, WString& output)override
|
|
{
|
|
return TypedValueSerializerProvider<T>::Serialize(UnboxValue<T>(input), output);
|
|
}
|
|
|
|
bool Deserialize(const WString& input, Value& output)override
|
|
{
|
|
T value;
|
|
if (!TypedValueSerializerProvider<T>::Deserialize(input, value))
|
|
{
|
|
return false;
|
|
}
|
|
output = BoxValue<T>(value);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
template<typename T>
|
|
class PrimitiveTypeDescriptor : public TypedValueTypeDescriptorBase<T, TypeDescriptorFlags::Primitive>
|
|
{
|
|
protected:
|
|
void LoadInternal()override
|
|
{
|
|
this->valueType = Ptr(new SerializableValueType<T>());
|
|
this->serializableType = Ptr(new SerializableType<T>());
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
EnumTypeDescriptor
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class EnumValueType : public Object, public virtual IValueType
|
|
{
|
|
public:
|
|
Value CreateDefault()override
|
|
{
|
|
return BoxValue<T>(static_cast<T>(0));
|
|
}
|
|
};
|
|
|
|
template<typename T, bool Flag>
|
|
class EnumType : public Object, public virtual IEnumType
|
|
{
|
|
protected:
|
|
collections::Dictionary<WString, T> candidates;
|
|
|
|
public:
|
|
void AddItem(WString name, T value)
|
|
{
|
|
candidates.Add(name, value);
|
|
}
|
|
|
|
bool IsFlagEnum()override
|
|
{
|
|
return Flag;
|
|
}
|
|
|
|
vint GetItemCount()override
|
|
{
|
|
return candidates.Count();
|
|
}
|
|
|
|
WString GetItemName(vint index)override
|
|
{
|
|
if (index < 0 || index >= candidates.Count())
|
|
{
|
|
return L"";
|
|
}
|
|
return candidates.Keys()[index];
|
|
}
|
|
|
|
vuint64_t GetItemValue(vint index)override
|
|
{
|
|
if (index < 0 || index >= candidates.Count())
|
|
{
|
|
return 0;
|
|
}
|
|
return static_cast<vuint64_t>(candidates.Values()[index]);
|
|
}
|
|
|
|
vint IndexOfItem(WString name)override
|
|
{
|
|
return candidates.Keys().IndexOf(name);
|
|
}
|
|
|
|
Value ToEnum(vuint64_t value)override
|
|
{
|
|
return BoxValue<T>(static_cast<T>(value));
|
|
}
|
|
|
|
vuint64_t FromEnum(const Value& value)override
|
|
{
|
|
return static_cast<vuint64_t>(UnboxValue<T>(value));
|
|
}
|
|
};
|
|
|
|
template<typename T, TypeDescriptorFlags TDFlags>
|
|
class EnumTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
|
|
{
|
|
using TEnumType = EnumType<T, TDFlags == TypeDescriptorFlags::FlagEnum>;
|
|
protected:
|
|
Ptr<TEnumType> enumType;
|
|
|
|
void LoadInternal()override
|
|
{
|
|
this->enumType = Ptr(new TEnumType);
|
|
this->valueType = Ptr(new EnumValueType<T>());
|
|
TypedValueTypeDescriptorBase<T, TDFlags>::enumType = enumType;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
StructTypeDescriptor
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class StructValueType : public Object, public virtual IValueType
|
|
{
|
|
public:
|
|
Value CreateDefault()override
|
|
{
|
|
return BoxValue<T>(T{});
|
|
}
|
|
};
|
|
|
|
template<typename T, TypeDescriptorFlags TDFlags>
|
|
class StructTypeDescriptor : public TypedValueTypeDescriptorBase<T, TDFlags>
|
|
{
|
|
protected:
|
|
template<typename TField>
|
|
class StructFieldInfo : public FieldInfoImpl
|
|
{
|
|
protected:
|
|
TField T::* field;
|
|
|
|
Value GetValueInternal(const Value& thisObject)override
|
|
{
|
|
auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
|
|
if (!structValue)
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
|
|
}
|
|
return BoxValue<TField>(structValue->value.*field);
|
|
}
|
|
|
|
void SetValueInternal(Value& thisObject, const Value& newValue)override
|
|
{
|
|
auto structValue = thisObject.GetBoxedValue().Cast<IValueType::TypedBox<T>>();
|
|
if (!structValue)
|
|
{
|
|
throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject);
|
|
}
|
|
(structValue->value.*field) = UnboxValue<TField>(newValue);
|
|
}
|
|
public:
|
|
StructFieldInfo(ITypeDescriptor* _ownerTypeDescriptor, TField T::* _field, const WString& _name)
|
|
:field(_field)
|
|
, FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver<TField>::CreateTypeInfo())
|
|
{
|
|
}
|
|
|
|
IPropertyInfo::ICpp* GetCpp()override
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
protected:
|
|
collections::Dictionary<WString, Ptr<IPropertyInfo>> fields;
|
|
|
|
public:
|
|
StructTypeDescriptor()
|
|
{
|
|
this->valueType = Ptr(new StructValueType<T>());
|
|
}
|
|
|
|
vint GetPropertyCount()override
|
|
{
|
|
this->Load();
|
|
return fields.Count();
|
|
}
|
|
|
|
IPropertyInfo* GetProperty(vint index)override
|
|
{
|
|
this->Load();
|
|
if (index < 0 || index >= fields.Count())
|
|
{
|
|
return nullptr;
|
|
}
|
|
return fields.Values()[index].Obj();
|
|
}
|
|
|
|
bool IsPropertyExists(const WString& name, bool inheritable)override
|
|
{
|
|
this->Load();
|
|
return fields.Keys().Contains(name);
|
|
}
|
|
|
|
IPropertyInfo* GetPropertyByName(const WString& name, bool inheritable)override
|
|
{
|
|
this->Load();
|
|
vint index = fields.Keys().IndexOf(name);
|
|
if (index == -1) return nullptr;
|
|
return fields.Values()[index].Obj();
|
|
}
|
|
};
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\BOXING\TYPEINFORETRIVER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_TYPEINFORETRIVER
|
|
#define VCZH_REFLECTION_BOXING_TYPEINFORETRIVER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
TypeFlagTester
|
|
***********************************************************************/
|
|
|
|
enum class TypeFlags
|
|
{
|
|
NonGenericType =0,
|
|
FunctionType =1<<0,
|
|
EnumerableType =1<<1,
|
|
ReadonlyListType =1<<2,
|
|
ArrayType =1<<3,
|
|
ListType =1<<4,
|
|
ObservableListType =1<<5,
|
|
ReadonlyDictionaryType =1<<6,
|
|
DictionaryType =1<<7,
|
|
};
|
|
|
|
template<typename T>
|
|
struct ValueRetriver
|
|
{
|
|
T* pointer;
|
|
};
|
|
|
|
template<typename T>
|
|
struct ValueRetriver<T&>
|
|
{
|
|
T* pointer;
|
|
};
|
|
|
|
template<typename TDerived, TypeFlags Flag>
|
|
struct TypeFlagTester
|
|
{
|
|
static const TypeFlags Result=TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::FunctionType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(const Func<T>* source){ return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::FunctionType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::EnumerableType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(const collections::LazyList<T>* source){ return {}; }
|
|
template<typename T>
|
|
static void* Inherit(const collections::IEnumerable<T>* source) { return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::EnumerableType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::ReadonlyListType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(const collections::Array<T>* source){ return {}; }
|
|
template<typename T>
|
|
static void* Inherit(const collections::List<T>* source) { return {}; }
|
|
template<typename T>
|
|
static void* Inherit(const collections::SortedList<T>* source) { return {}; }
|
|
template<typename T>
|
|
static void* Inherit(const collections::ObservableListBase<T>* source) { return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyListType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::ArrayType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(collections::Array<T>* source) { return {}; }
|
|
static char Inherit(void* source) { return {}; }
|
|
static char Inherit(const void* source) { return {}; }
|
|
|
|
static const TypeFlags Result = sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer)) == sizeof(void*) ? TypeFlags::ArrayType : TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::ListType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(collections::List<T>* source) { return {}; }
|
|
template<typename T>
|
|
static void* Inherit(collections::ObservableListBase<T>* source) { return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ListType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::ObservableListType>
|
|
{
|
|
template<typename T>
|
|
static void* Inherit(collections::ObservableList<T>* source) { return {}; }
|
|
static char Inherit(void* source) { return {}; }
|
|
static char Inherit(const void* source) { return {}; }
|
|
|
|
static const TypeFlags Result = sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer)) == sizeof(void*) ? TypeFlags::ObservableListType : TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::ReadonlyDictionaryType>
|
|
{
|
|
template<typename K, typename V>
|
|
static void* Inherit(const collections::Dictionary<K, V>* source){ return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyDictionaryType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename TDerived>
|
|
struct TypeFlagTester<TDerived, TypeFlags::DictionaryType>
|
|
{
|
|
template<typename K, typename V>
|
|
static void* Inherit(collections::Dictionary<K, V>* source){ return {}; }
|
|
static char Inherit(void* source){ return {}; }
|
|
static char Inherit(const void* source){ return {}; }
|
|
|
|
static const TypeFlags Result=sizeof(Inherit(((ValueRetriver<TDerived>*)0)->pointer))==sizeof(void*)?TypeFlags::DictionaryType:TypeFlags::NonGenericType;
|
|
};
|
|
|
|
/***********************************************************************
|
|
TypeFlagSelector
|
|
***********************************************************************/
|
|
|
|
template<typename T, TypeFlags Flag>
|
|
struct TypeFlagSelectorCase
|
|
{
|
|
static const TypeFlags Result=TypeFlags::NonGenericType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::FunctionType)>
|
|
{
|
|
static const TypeFlags Result=TypeFlags::FunctionType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType)>
|
|
{
|
|
static const TypeFlags Result=TypeFlags::EnumerableType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType)>
|
|
{
|
|
static const TypeFlags Result = TypeFlags::ReadonlyListType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ArrayType)>
|
|
{
|
|
static const TypeFlags Result = TypeFlags::ArrayType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ListType)>
|
|
{
|
|
static const TypeFlags Result = TypeFlags::ListType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyListType|(vint)TypeFlags::ListType|(vint)TypeFlags::ObservableListType)>
|
|
{
|
|
static const TypeFlags Result = TypeFlags::ObservableListType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType|(vint)TypeFlags::ReadonlyDictionaryType)>
|
|
{
|
|
static const TypeFlags Result=TypeFlags::ReadonlyDictionaryType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelectorCase<T, (TypeFlags)((vint)TypeFlags::EnumerableType |(vint)TypeFlags::ReadonlyDictionaryType |(vint)TypeFlags::DictionaryType)>
|
|
{
|
|
static const TypeFlags Result=TypeFlags::DictionaryType;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeFlagSelector
|
|
{
|
|
static const TypeFlags Result =
|
|
TypeFlagSelectorCase<
|
|
T,
|
|
(TypeFlags)
|
|
( (vint)TypeFlagTester<T, TypeFlags::FunctionType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::EnumerableType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::ReadonlyListType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::ArrayType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::ListType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::ObservableListType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::ReadonlyDictionaryType>::Result
|
|
| (vint)TypeFlagTester<T, TypeFlags::DictionaryType>::Result
|
|
)
|
|
>::Result;
|
|
};
|
|
|
|
/***********************************************************************
|
|
TypeHintTester
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypeHintTester
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::Normal;
|
|
};
|
|
|
|
template<TypeFlags Flags>
|
|
struct TypeHintTesterForReference
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::NativeCollectionReference;
|
|
};
|
|
|
|
template<>
|
|
struct TypeHintTesterForReference<TypeFlags::NonGenericType>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::Normal;
|
|
};
|
|
|
|
template<>
|
|
struct TypeHintTesterForReference<TypeFlags::FunctionType>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::Normal;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<T*>
|
|
{
|
|
static const TypeInfoHint Result = TypeHintTester<T>::Result;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<T&>
|
|
{
|
|
static const TypeInfoHint Result = TypeHintTester<T>::Result == TypeInfoHint::Normal
|
|
? TypeHintTesterForReference<TypeFlagSelector<T&>::Result>::Result
|
|
: TypeHintTester<T>::Result
|
|
;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<const T>
|
|
{
|
|
static const TypeInfoHint Result = TypeHintTester<T>::Result;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<collections::LazyList<T>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::LazyList;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<collections::Array<T>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::Array;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<collections::List<T>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::List;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<collections::SortedList<T>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::SortedList;
|
|
};
|
|
|
|
template<typename T>
|
|
struct TypeHintTester<collections::ObservableList<T>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::ObservableList;
|
|
};
|
|
|
|
template<typename K, typename V>
|
|
struct TypeHintTester<collections::Dictionary<K, V>>
|
|
{
|
|
static const TypeInfoHint Result = TypeInfoHint::Dictionary;
|
|
};
|
|
|
|
/***********************************************************************
|
|
DetailTypeInfoRetriver
|
|
***********************************************************************/
|
|
|
|
template<typename T, TypeFlags Flag>
|
|
struct DetailTypeInfoRetriver;
|
|
|
|
/***********************************************************************
|
|
Basic Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::NonGenericType>
|
|
{
|
|
static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
return Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<T>(), hint));
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/***********************************************************************
|
|
Decorated Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T*, TypeFlags::NonGenericType>
|
|
{
|
|
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator=ITypeInfo::RawPtr;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
return Ptr(new RawPtrTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<Ptr<T>, TypeFlags::NonGenericType>
|
|
{
|
|
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator=ITypeInfo::SharedPtr;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
return Ptr(new SharedPtrTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<Nullable<T>, TypeFlags::NonGenericType>
|
|
{
|
|
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator=ITypeInfo::Nullable;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
return Ptr(new NullableTypeInfo(TypeInfoRetriver<T>::CreateTypeInfo()));
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/***********************************************************************
|
|
Containers
|
|
***********************************************************************/
|
|
|
|
template<typename T, typename TCollectionType>
|
|
struct DetailTypeInfoRetriver_Template1
|
|
{
|
|
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
auto arrayType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<TCollectionType>(), hint));
|
|
|
|
auto genericType = Ptr(new GenericTypeInfo(arrayType));
|
|
genericType->AddGenericArgument(TypeInfoRetriver<typename T::ElementType>::CreateTypeInfo());
|
|
|
|
auto type = Ptr(new SharedPtrTypeInfo(genericType));
|
|
return type;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template<typename T, typename TCollectionType>
|
|
struct DetailTypeInfoRetriver_Template2
|
|
{
|
|
typedef DetailTypeInfoRetriver<T, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
auto arrayType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<TCollectionType>(), hint));
|
|
|
|
auto genericType = Ptr(new GenericTypeInfo(arrayType));
|
|
genericType->AddGenericArgument(TypeInfoRetriver<typename T::KeyContainer::ElementType>::CreateTypeInfo());
|
|
genericType->AddGenericArgument(TypeInfoRetriver<typename T::ValueContainer::ElementType>::CreateTypeInfo());
|
|
|
|
auto type = Ptr(new SharedPtrTypeInfo(genericType));
|
|
return type;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::EnumerableType> : DetailTypeInfoRetriver_Template1<T, IValueEnumerable>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyListType> : DetailTypeInfoRetriver_Template1<T, IValueReadonlyList>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::ArrayType> : DetailTypeInfoRetriver_Template1<T, IValueArray>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::ListType> : DetailTypeInfoRetriver_Template1<T, IValueList>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::ObservableListType> : DetailTypeInfoRetriver_Template1<T, IValueObservableList>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::ReadonlyDictionaryType> : DetailTypeInfoRetriver_Template2<T, IValueReadonlyDictionary>
|
|
{
|
|
};
|
|
|
|
template<typename T>
|
|
struct DetailTypeInfoRetriver<T, TypeFlags::DictionaryType> : DetailTypeInfoRetriver_Template2<T, IValueDictionary>
|
|
{
|
|
};
|
|
|
|
/***********************************************************************
|
|
Functions
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
namespace internal_helper
|
|
{
|
|
template<typename T>
|
|
struct GenericArgumentAdder
|
|
{
|
|
static void Add(Ptr<GenericTypeInfo> genericType)
|
|
{
|
|
}
|
|
};
|
|
|
|
template<typename T0, typename ...TNextArgs>
|
|
struct GenericArgumentAdder<TypeTuple<T0, TNextArgs...>>
|
|
{
|
|
static void Add(Ptr<GenericTypeInfo> genericType)
|
|
{
|
|
genericType->AddGenericArgument(TypeInfoRetriver<T0>::CreateTypeInfo());
|
|
GenericArgumentAdder<TypeTuple<TNextArgs...>>::Add(genericType);
|
|
}
|
|
};
|
|
}
|
|
#endif
|
|
|
|
template<typename R, typename ...TArgs>
|
|
struct DetailTypeInfoRetriver<Func<R(TArgs...)>, TypeFlags::FunctionType>
|
|
{
|
|
typedef DetailTypeInfoRetriver<const Func<R(TArgs...)>, TypeFlags::NonGenericType> UpLevelRetriver;
|
|
|
|
static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo(TypeInfoHint hint)
|
|
{
|
|
auto functionType = Ptr(new TypeDescriptorTypeInfo(GetTypeDescriptor<IValueFunctionProxy>(), hint));
|
|
|
|
auto genericType = Ptr(new GenericTypeInfo(functionType));
|
|
genericType->AddGenericArgument(TypeInfoRetriver<R>::CreateTypeInfo());
|
|
internal_helper::GenericArgumentAdder<TypeTuple<TArgs...>>::Add(genericType);
|
|
|
|
auto type = Ptr(new SharedPtrTypeInfo(genericType));
|
|
return type;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/***********************************************************************
|
|
TypeInfoRetriver
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct TypeInfoRetriver
|
|
{
|
|
static const TypeFlags TypeFlag = TypeFlagSelector<T>::Result;
|
|
static const TypeInfoHint Hint = TypeHintTester<T>::Result;
|
|
typedef DetailTypeInfoRetriver<std::remove_cvref_t<T>, TypeFlag> Detail;
|
|
static const ITypeInfo::Decorator Decorator = Detail::Decorator;
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
static Ptr<ITypeInfo> CreateTypeInfo()
|
|
{
|
|
return DetailTypeInfoRetriver<std::remove_cvref_t<T>, TypeFlag>::CreateTypeInfo(Hint);
|
|
}
|
|
#endif
|
|
};
|
|
|
|
template<>
|
|
struct TypeInfoRetriver<void> : public TypeInfoRetriver<VoidValue>
|
|
{
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\BOXING\BOXINGVALUE.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_BOXINGVALUE
|
|
#define VCZH_REFLECTION_BOXING_BOXINGVALUE
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
BoxValue, UnboxValue
|
|
***********************************************************************/
|
|
|
|
template<typename T, ITypeInfo::Decorator Decorator>
|
|
struct ValueAccessor
|
|
{
|
|
};
|
|
|
|
/// <summary>Box an reflectable object. Its type cannot be generic.</summary>
|
|
/// <returns>The boxed value.</returns>
|
|
/// <typeparam name="T">Type of the object.</typeparam>
|
|
/// <param name="object">The object to box.</param>
|
|
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
|
|
template<typename T>
|
|
Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
using Type = std::remove_cvref_t<T>;
|
|
return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::BoxValue(object, typeDescriptor);
|
|
}
|
|
|
|
/// <summary>Unbox a reflectable object. Its type cannot be generic.</summary>
|
|
/// <returns>The unboxed object.</returns>
|
|
/// <typeparam name="T">Type of the object.</typeparam>
|
|
/// <param name="value">The value to unbox.</param>
|
|
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
|
|
/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
|
|
template<typename T>
|
|
T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
using Type = std::remove_cvref_t<T>;
|
|
return ValueAccessor<Type, TypeInfoRetriver<Type>::Decorator>::UnboxValue(value, typeDescriptor, valueName);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Basic Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct ValueAccessor<T*, ITypeInfo::RawPtr>
|
|
{
|
|
static Value BoxValue(T* object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return Value::From(object);
|
|
}
|
|
|
|
static T* UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
if(value.IsNull()) return nullptr;
|
|
T* result = nullptr;
|
|
if (value.GetRawPtr())
|
|
{
|
|
result = value.GetRawPtr()->SafeAggregationCast<T>();
|
|
}
|
|
if(!result)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(!typeDescriptor)
|
|
{
|
|
typeDescriptor=GetTypeDescriptor<T>();
|
|
}
|
|
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::RawPtr, value);
|
|
#else
|
|
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
|
|
#endif
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ValueAccessor<Ptr<T>, ITypeInfo::SharedPtr>
|
|
{
|
|
static Value BoxValue(Ptr<T> object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return Value::From(object);
|
|
}
|
|
|
|
static Ptr<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
if (value.IsNull()) return nullptr;
|
|
Ptr<T> result;
|
|
if(value.GetValueType()==Value::RawPtr || value.GetValueType()==Value::SharedPtr)
|
|
{
|
|
result = Ptr(value.GetRawPtr()->SafeAggregationCast<T>());
|
|
}
|
|
if(!result)
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(!typeDescriptor)
|
|
{
|
|
typeDescriptor=GetTypeDescriptor<T>();
|
|
}
|
|
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::SharedPtr, value);
|
|
#else
|
|
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
|
|
#endif
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ValueAccessor<Nullable<T>, ITypeInfo::Nullable>
|
|
{
|
|
static Value BoxValue(Nullable<T> object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return object?ValueAccessor<T, ITypeInfo::TypeDescriptor>::BoxValue(object.Value(), typeDescriptor):Value();
|
|
}
|
|
|
|
static Nullable<T> UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
if(value.IsNull())
|
|
{
|
|
return Nullable<T>();
|
|
}
|
|
else
|
|
{
|
|
return ValueAccessor<T, ITypeInfo::TypeDescriptor>::UnboxValue(value, typeDescriptor, valueName);
|
|
}
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ValueAccessor<T, ITypeInfo::TypeDescriptor>
|
|
{
|
|
static Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
using Type = std::remove_cvref_t<T>;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if(!typeDescriptor)
|
|
{
|
|
typeDescriptor = GetTypeDescriptor<Type>();
|
|
}
|
|
#endif
|
|
return Value::From(Ptr(new IValueType::TypedBox<Type>(object)), typeDescriptor);
|
|
}
|
|
|
|
static T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
using Type = std::remove_cvref_t<T>;
|
|
if (auto unboxedValue = value.GetBoxedValue().Cast<IValueType::TypedBox<Type>>())
|
|
{
|
|
return unboxedValue->value;
|
|
}
|
|
else
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (!typeDescriptor)
|
|
{
|
|
typeDescriptor = GetTypeDescriptor<Type>();
|
|
}
|
|
throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::BoxedValue, value);
|
|
#else
|
|
CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch.");
|
|
#endif
|
|
}
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct ValueAccessor<Value, ITypeInfo::TypeDescriptor>
|
|
{
|
|
static Value BoxValue(const Value& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return object;
|
|
}
|
|
|
|
static Value UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct ValueAccessor<VoidValue, ITypeInfo::TypeDescriptor>
|
|
{
|
|
static Value BoxValue(const VoidValue& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return Value();
|
|
}
|
|
|
|
static VoidValue UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return VoidValue();
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\BOXING\BOXINGPARAMETER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER
|
|
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
BoxParameter, UnboxParameter
|
|
***********************************************************************/
|
|
|
|
template<typename T, TypeFlags Flag>
|
|
struct ParameterAccessor
|
|
{
|
|
};
|
|
|
|
/// <summary>Box an reflectable object. It supports generic types such as containers, functions (should be Func<T>), etc.</summary>
|
|
/// <returns>The boxed value.</returns>
|
|
/// <typeparam name="T">Type of the object.</typeparam>
|
|
/// <param name="object">The object to box.</param>
|
|
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
|
|
template<typename T>
|
|
Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
using TIR = TypeInfoRetriver<std::remove_reference_t<T>>;
|
|
return ParameterAccessor<std::remove_reference_t<T>, TIR::TypeFlag>::BoxParameter(object, typeDescriptor);
|
|
}
|
|
|
|
/// <summary>Box an reflectable object. It supports generic types such as containers, functions (should be Func<T>), etc.</summary>
|
|
/// <typeparam name="T">Type of the object.</typeparam>
|
|
/// <returns>The unboxed object. It could be the same object that is boxed, or it could be a new object.</returns>
|
|
/// <param name="value">The value to unbox.</param>
|
|
/// <param name="typeDescriptor">The type descriptor of the object (optional).</param>
|
|
/// <param name="valueName">The name of the object to provide a friendly exception message if the conversion is failed (optional).</param>
|
|
template<typename T>
|
|
Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor , const WString& valueName)
|
|
{
|
|
using TIR = TypeInfoRetriver<std::remove_reference_t<T>>;
|
|
return ParameterAccessor<T, TIR::TypeFlag>::UnboxParameter(value, typeDescriptor, valueName);
|
|
}
|
|
|
|
/***********************************************************************
|
|
BoxParametersToList
|
|
***********************************************************************/
|
|
|
|
inline void BoxParametersToList(Ptr<IValueList> arguments) {}
|
|
|
|
template<typename T0, typename ...TArgs>
|
|
void BoxParametersToList(Ptr<IValueList> arguments, T0&& p0, TArgs&& ...args)
|
|
{
|
|
arguments->Add(description::BoxParameter(p0));
|
|
BoxParametersToList(arguments, args...);
|
|
}
|
|
|
|
class Value_xs
|
|
{
|
|
protected:
|
|
collections::Array<Value> arguments;
|
|
public:
|
|
Value_xs()
|
|
{
|
|
}
|
|
|
|
template<typename T>
|
|
Value_xs& operator,(T& value)
|
|
{
|
|
arguments.Resize(arguments.Count() + 1);
|
|
arguments[arguments.Count() - 1] = BoxParameter(value);
|
|
return *this;
|
|
}
|
|
|
|
Value_xs& operator,(const Value& value)
|
|
{
|
|
arguments.Resize(arguments.Count() + 1);
|
|
arguments[arguments.Count() - 1] = value;
|
|
return *this;
|
|
}
|
|
|
|
operator collections::Array<Value>& ()
|
|
{
|
|
return arguments;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Basic Types
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::NonGenericType>
|
|
{
|
|
static Value BoxParameter(const T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return BoxValue<T>(object, typeDescriptor);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return { new T(std::move(UnboxValue<T>(value, typeDescriptor, valueName))), true };
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\BOXING\INVOKEWITHBOXEDPARAMETERS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_INVOKEWITHBOXEDPARAMETERS
|
|
#define VCZH_REFLECTION_BOXING_INVOKEWITHBOXEDPARAMETERS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
UnboxAndCall
|
|
***********************************************************************/
|
|
|
|
namespace unboxcall_helper
|
|
{
|
|
template<typename T, vint I>
|
|
struct ArgPack
|
|
{
|
|
using TArg = T;
|
|
static const vint Index = I;
|
|
};
|
|
|
|
template<typename ...TArgs>
|
|
struct ArgPacks
|
|
{
|
|
};
|
|
|
|
template<typename TArgPacks, typename ...TArgs>
|
|
struct MakeArgPacks_;
|
|
|
|
template<typename ...TPacked>
|
|
struct MakeArgPacks_<ArgPacks<TPacked...>>
|
|
{
|
|
using Type = ArgPacks<TPacked...>;
|
|
};
|
|
|
|
template<typename ...TPacked, typename T0, typename ...TArgs>
|
|
struct MakeArgPacks_<ArgPacks<TPacked...>, T0, TArgs...>
|
|
{
|
|
using Type = typename MakeArgPacks_<ArgPacks<TPacked..., ArgPack<T0, sizeof...(TPacked)>>, TArgs...>::Type;
|
|
};
|
|
}
|
|
|
|
template<typename ...TArgs>
|
|
using MakeArgPacks = typename unboxcall_helper::MakeArgPacks_<unboxcall_helper::ArgPacks<>, TArgs...>::Type;
|
|
|
|
namespace unboxcall_helper
|
|
{
|
|
template<typename TArgPacks>
|
|
struct Unbox;
|
|
|
|
template<typename ...TArgPacks>
|
|
struct Unbox<ArgPacks<TArgPacks...>>
|
|
{
|
|
template<typename TFunction>
|
|
static auto AndCallObject(TFunction&& function, IMethodInfo* methodInfo, const Ptr<IValueReadonlyList>& arguments) -> decltype(function(std::declval<typename TArgPacks::TArg>()...))
|
|
{
|
|
// function(arguments)
|
|
return function(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
|
|
arguments->Get(TArgPacks::Index),
|
|
(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
|
|
).Ref()...);
|
|
}
|
|
|
|
template<typename TFunction>
|
|
static auto AndCallFunction(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments) -> decltype(function(std::declval<typename TArgPacks::TArg>()...))
|
|
{
|
|
// function(arguments)
|
|
return function(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
|
|
arguments[TArgPacks::Index],
|
|
(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
|
|
).Ref()...);
|
|
}
|
|
|
|
template<typename TClass, typename TFunction>
|
|
static auto AndCallMethod(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments, TClass* object) -> decltype((object->*function)(std::declval<typename TArgPacks::TArg>()...))
|
|
{
|
|
// (object->*function)(arguments)
|
|
return (object->*function)(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
|
|
arguments[TArgPacks::Index],
|
|
(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
|
|
).Ref()...);
|
|
}
|
|
|
|
template<typename TClass, typename TFunction>
|
|
static auto AndCallExternal(TFunction function, IMethodInfo* methodInfo, collections::Array<Value>& arguments, TClass* object) -> decltype(function(object, std::declval<typename TArgPacks::TArg>()...))
|
|
{
|
|
// function(object, arguments)
|
|
return function(
|
|
object,
|
|
UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
|
|
arguments[TArgPacks::Index],
|
|
(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
|
|
).Ref()...
|
|
);
|
|
}
|
|
|
|
template<typename TClass, typename R>
|
|
static R AndNew(IMethodInfo* methodInfo, collections::Array<Value>& arguments)
|
|
{
|
|
// new TClass(arguments)
|
|
return R(new TClass(UnboxParameter<std::remove_cvref_t<typename TArgPacks::TArg>>(
|
|
arguments[TArgPacks::Index],
|
|
(methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr)
|
|
).Ref()...));
|
|
}
|
|
};
|
|
}
|
|
|
|
/***********************************************************************
|
|
Invoke
|
|
***********************************************************************/
|
|
|
|
namespace invoke_helper
|
|
{
|
|
template<typename TClass, typename R, typename ...TArgs>
|
|
Value InvokeMethod(TClass* object, R(__thiscall TClass::* method)(TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
|
|
{
|
|
using TArgPacks = MakeArgPacks<TArgs...>;
|
|
if constexpr (std::is_same_v<R, void>)
|
|
{
|
|
unboxcall_helper::Unbox<TArgPacks>::AndCallMethod(method, methodInfo, arguments, object);
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
|
|
return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallMethod(method, methodInfo, arguments, object), td);
|
|
}
|
|
}
|
|
|
|
template<typename TClass, typename R, typename ...TArgs>
|
|
Value InvokeExternal(TClass* object, R(*method)(TClass*, TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
|
|
{
|
|
using TArgPacks = MakeArgPacks<TArgs...>;
|
|
if constexpr (std::is_same_v<R, void>)
|
|
{
|
|
unboxcall_helper::Unbox<TArgPacks>::AndCallExternal(method, methodInfo, arguments, object);
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
|
|
return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallExternal(method, methodInfo, arguments, object), td);
|
|
}
|
|
}
|
|
|
|
template<typename R, typename ...TArgs>
|
|
Value InvokeFunction(R(*method)(TArgs...), IMethodInfo* methodInfo, collections::Array<Value>& arguments)
|
|
{
|
|
using TArgPacks = MakeArgPacks<TArgs...>;
|
|
if constexpr (std::is_same_v<R, void>)
|
|
{
|
|
unboxcall_helper::Unbox<TArgPacks>::AndCallFunction(method, methodInfo, arguments);
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
|
|
return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallFunction(method, methodInfo, arguments), td);
|
|
}
|
|
}
|
|
|
|
template<typename TFunction, typename ...TArgs>
|
|
Value InvokeObject(TFunction& function, IMethodInfo* methodInfo, const Ptr<IValueReadonlyList>& arguments)
|
|
{
|
|
using TArgPacks = MakeArgPacks<TArgs...>;
|
|
using TResult = decltype(unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments));
|
|
if constexpr (std::is_same_v<TResult, void>)
|
|
{
|
|
unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments);
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr;
|
|
return BoxParameter(unboxcall_helper::Unbox<TArgPacks>::AndCallObject(function, methodInfo, arguments), td);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\WRAPPERS\CONTAINERWRAPPERS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_WRAPPERS_CONTAINERWRAPPERS
|
|
#define VCZH_REFLECTION_WRAPPERS_CONTAINERWRAPPERS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
/***********************************************************************
|
|
Enumerable Wrappers
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class TypedEnumerator : public Object, public collections::IEnumerator<T>
|
|
{
|
|
private:
|
|
Ptr<IValueEnumerable> enumerable;
|
|
Ptr<IValueEnumerator> enumerator;
|
|
vint index;
|
|
T value;
|
|
|
|
public:
|
|
TypedEnumerator(Ptr<IValueEnumerable> _enumerable, vint _index, const T& _value)
|
|
:enumerable(_enumerable)
|
|
,index(_index)
|
|
,value(_value)
|
|
{
|
|
enumerator=enumerable->CreateEnumerator();
|
|
vint current=-1;
|
|
while(current++<index)
|
|
{
|
|
enumerator->Next();
|
|
}
|
|
}
|
|
|
|
TypedEnumerator(Ptr<IValueEnumerable> _enumerable)
|
|
:enumerable(_enumerable)
|
|
,index(-1)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
collections::IEnumerator<T>* Clone()const override
|
|
{
|
|
return new TypedEnumerator<T>(enumerable, index, value);
|
|
}
|
|
|
|
const T& Current()const override
|
|
{
|
|
return value;
|
|
}
|
|
|
|
vint Index()const override
|
|
{
|
|
return index;
|
|
}
|
|
|
|
bool Next() override
|
|
{
|
|
if(enumerator->Next())
|
|
{
|
|
index++;
|
|
value=UnboxValue<T>(enumerator->GetCurrent());
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void Reset() override
|
|
{
|
|
index=-1;
|
|
enumerator=enumerable->CreateEnumerator();
|
|
}
|
|
};
|
|
|
|
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="T">The expected element type.</typeparam>
|
|
/// <param name="value">The reflectable container.</param>
|
|
template<typename T>
|
|
collections::LazyList<T> GetLazyList(Ptr<IValueEnumerable> value)
|
|
{
|
|
return collections::LazyList<T>(new TypedEnumerator<T>(value));
|
|
}
|
|
|
|
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="T">The expected element type.</typeparam>
|
|
/// <param name="value">The reflectable container.</param>
|
|
template<typename T>
|
|
collections::LazyList<T> GetLazyList(Ptr<IValueReadonlyList> value)
|
|
{
|
|
return collections::Range<vint>(0, value->GetCount())
|
|
.Select([value](vint i)
|
|
{
|
|
return UnboxValue<T>(value->Get(i));
|
|
});
|
|
}
|
|
|
|
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="T">The expected element type.</typeparam>
|
|
/// <param name="value">The reflectable container.</param>
|
|
template<typename T>
|
|
collections::LazyList<T> GetLazyList(Ptr<IValueArray> value)
|
|
{
|
|
return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
|
|
}
|
|
|
|
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="T">The expected element type.</typeparam>
|
|
/// <param name="value">The reflectable container.</param>
|
|
template<typename T>
|
|
collections::LazyList<T> GetLazyList(Ptr<IValueList> value)
|
|
{
|
|
return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
|
|
}
|
|
|
|
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="T">The expected element type.</typeparam>
|
|
/// <param name="value">The reflectable container.</param>
|
|
template<typename T>
|
|
collections::LazyList<T> GetLazyList(Ptr<IValueObservableList> value)
|
|
{
|
|
return GetLazyList<T>(Ptr<IValueReadonlyList>(value));
|
|
}
|
|
|
|
/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="K">The expected key type.</typeparam>
|
|
/// <typeparam name="V">The expected value type.</typeparam>
|
|
/// <param name="value">The reflectable dictionary.</param>
|
|
template<typename K, typename V>
|
|
collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueReadonlyDictionary> value)
|
|
{
|
|
return collections::Range<vint>(0, value->GetCount())
|
|
.Select([value](vint i)
|
|
{
|
|
return collections::Pair<K, V>(UnboxValue<K>(value->GetKeys()->Get(i)), UnboxValue<V>(value->GetValues()->Get(i)));
|
|
});
|
|
}
|
|
|
|
/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
|
|
/// <returns>The created lazy list.</returns>
|
|
/// <typeparam name="K">The expected key type.</typeparam>
|
|
/// <typeparam name="V">The expected value type.</typeparam>
|
|
/// <param name="value">The reflectable dictionary.</param>
|
|
template<typename K, typename V>
|
|
collections::LazyList<collections::Pair<K, V>> GetLazyList(Ptr<IValueDictionary> value)
|
|
{
|
|
return GetLazyList<K, V>(Ptr<IValueReadonlyDictionary>(value));
|
|
}
|
|
|
|
/***********************************************************************
|
|
Collection Wrappers
|
|
***********************************************************************/
|
|
|
|
namespace trait_helper
|
|
{
|
|
template<typename T>
|
|
struct RemovePtr
|
|
{
|
|
typedef T Type;
|
|
};
|
|
|
|
template<typename T>
|
|
struct RemovePtr<T*>
|
|
{
|
|
typedef T Type;
|
|
};
|
|
|
|
template<typename T>
|
|
struct RemovePtr<Ptr<T>>
|
|
{
|
|
typedef T Type;
|
|
};
|
|
}
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4250)
|
|
|
|
template<typename T>
|
|
class ValueEnumerableWrapper;
|
|
|
|
template<typename TWrapper, typename TEnumerator>
|
|
class ValueEnumeratorWrapper : public Object, public virtual IValueEnumerator
|
|
{
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<TEnumerator>::Type ContainerType;
|
|
typedef typename ContainerType::ElementType ElementType;
|
|
|
|
Ptr<TWrapper> enumerableWrapper;
|
|
TEnumerator wrapperPointer;
|
|
public:
|
|
ValueEnumeratorWrapper(const Ptr<TWrapper>& _enumerableWrapper, const TEnumerator& _wrapperPointer)
|
|
:enumerableWrapper(_enumerableWrapper)
|
|
, wrapperPointer(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
Value GetCurrent()override
|
|
{
|
|
if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
|
|
return BoxValue<ElementType>(wrapperPointer->Current());
|
|
}
|
|
|
|
vint GetIndex()override
|
|
{
|
|
if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
|
|
return wrapperPointer->Index();
|
|
}
|
|
|
|
bool Next()override
|
|
{
|
|
if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException();
|
|
return wrapperPointer->Next();
|
|
}
|
|
};
|
|
|
|
#define WRAPPER_POINTER this->wrapperPointer
|
|
#define ENSURE_WRAPPER_POINTER if (!WRAPPER_POINTER) throw ObjectDisposedException()
|
|
|
|
template<typename T>
|
|
class ValueEnumerableWrapper : public Object, public virtual collections::ICollectionReference, public virtual IValueEnumerable
|
|
{
|
|
template<typename TWrapper, typename TEnumerator>
|
|
friend class ValueEnumeratorWrapper;
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
|
|
typedef typename ContainerType::ElementType ElementType;
|
|
|
|
T wrapperPointer;
|
|
public:
|
|
ValueEnumerableWrapper(const T& _wrapperPointer)
|
|
:wrapperPointer(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
void OnDisposed()override
|
|
{
|
|
wrapperPointer = nullptr;
|
|
}
|
|
|
|
Ptr<IValueEnumerator> CreateEnumerator()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return Ptr(new ValueEnumeratorWrapper<
|
|
ValueEnumerableWrapper<T>,
|
|
Ptr<collections::IEnumerator<ElementType>>
|
|
>(
|
|
Ptr(this),
|
|
Ptr(wrapperPointer->CreateEnumerator())
|
|
));
|
|
}
|
|
|
|
const Object* GetCollectionObject()override
|
|
{
|
|
if constexpr (std::is_same_v<typename trait_helper::RemovePtr<T>::Type*, T>)
|
|
{
|
|
if (wrapperPointer->GetCollectionReference() == this)
|
|
{
|
|
return wrapperPointer;
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueReadonlyListWrapper : public ValueEnumerableWrapper<T>, public virtual IValueReadonlyList
|
|
{
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
|
|
typedef typename ContainerType::ElementType ElementType;
|
|
typedef typename KeyType<ElementType>::Type ElementKeyType;
|
|
|
|
public:
|
|
ValueReadonlyListWrapper(const T& _wrapperPointer)
|
|
:ValueEnumerableWrapper<T>(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
vint GetCount()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return WRAPPER_POINTER->Count();
|
|
}
|
|
|
|
Value Get(vint index)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return BoxValue<ElementType>(WRAPPER_POINTER->Get(index));
|
|
}
|
|
|
|
bool Contains(const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementKeyType item = UnboxValue<ElementKeyType>(value);
|
|
return WRAPPER_POINTER->Contains(item);
|
|
}
|
|
|
|
vint IndexOf(const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementKeyType item = UnboxValue<ElementKeyType>(value);
|
|
return WRAPPER_POINTER->IndexOf(item);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueArrayWrapper : public ValueReadonlyListWrapper<T>, public virtual IValueArray
|
|
{
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
|
|
typedef typename ContainerType::ElementType ElementType;
|
|
typedef typename KeyType<ElementType>::Type ElementKeyType;
|
|
|
|
public:
|
|
ValueArrayWrapper(const T& _wrapperPointer)
|
|
:ValueReadonlyListWrapper<T>(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
void Set(vint index, const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementType item = UnboxValue<ElementType>(value);
|
|
WRAPPER_POINTER->Set(index, item);
|
|
}
|
|
|
|
void Resize(vint size)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return WRAPPER_POINTER->Resize(size);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueListWrapper : public ValueReadonlyListWrapper<T>, public virtual IValueList
|
|
{
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
|
|
typedef typename ContainerType::ElementType ElementType;
|
|
typedef typename KeyType<ElementType>::Type ElementKeyType;
|
|
|
|
public:
|
|
ValueListWrapper(const T& _wrapperPointer)
|
|
:ValueReadonlyListWrapper<T>(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
void Set(vint index, const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementType item = UnboxValue<ElementType>(value);
|
|
WRAPPER_POINTER->Set(index, item);
|
|
}
|
|
|
|
vint Add(const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementType item = UnboxValue<ElementType>(value);
|
|
return WRAPPER_POINTER->Add(item);
|
|
}
|
|
|
|
vint Insert(vint index, const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementType item = UnboxValue<ElementType>(value);
|
|
return WRAPPER_POINTER->Insert(index, item);
|
|
}
|
|
|
|
bool Remove(const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
ElementKeyType item = UnboxValue<ElementKeyType>(value);
|
|
return WRAPPER_POINTER->Remove(item);
|
|
}
|
|
|
|
bool RemoveAt(vint index)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return WRAPPER_POINTER->RemoveAt(index);
|
|
}
|
|
|
|
void Clear()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
WRAPPER_POINTER->Clear();
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueObservableListWrapper : public ValueListWrapper<T>, public virtual IValueObservableList
|
|
{
|
|
public:
|
|
ValueObservableListWrapper(const T& _wrapperPointer)
|
|
:ValueListWrapper<T>(_wrapperPointer)
|
|
{
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
class ValueReadonlyDictionaryWrapper : public virtual Object, public virtual collections::ICollectionReference, public virtual IValueReadonlyDictionary
|
|
{
|
|
protected:
|
|
typedef typename trait_helper::RemovePtr<T>::Type ContainerType;
|
|
typedef typename ContainerType::KeyContainer KeyContainer;
|
|
typedef typename ContainerType::ValueContainer ValueContainer;
|
|
typedef typename KeyContainer::ElementType KeyValueType;
|
|
typedef typename KeyType<KeyValueType>::Type KeyKeyType;
|
|
typedef typename ValueContainer::ElementType ValueType;
|
|
|
|
T wrapperPointer;
|
|
Ptr<IValueReadonlyList> keys;
|
|
Ptr<IValueReadonlyList> values;
|
|
public:
|
|
ValueReadonlyDictionaryWrapper(const T& _wrapperPointer)
|
|
:wrapperPointer(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
void OnDisposed()override
|
|
{
|
|
wrapperPointer = nullptr;
|
|
keys = nullptr;
|
|
values = nullptr;
|
|
}
|
|
|
|
Ptr<IValueReadonlyList> GetKeys()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
if (!keys)
|
|
{
|
|
keys = UnboxValue<Ptr<IValueReadonlyList>>(BoxParameter(wrapperPointer->Keys()));
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
Ptr<IValueReadonlyList> GetValues()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
if (!values)
|
|
{
|
|
values = UnboxValue<Ptr<IValueReadonlyList>>(BoxParameter(wrapperPointer->Values()));
|
|
}
|
|
return values;
|
|
}
|
|
|
|
vint GetCount()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
return wrapperPointer->Count();
|
|
}
|
|
|
|
Value Get(const Value& key)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
KeyKeyType item = UnboxValue<KeyKeyType>(key);
|
|
ValueType result = wrapperPointer->Get(item);
|
|
return BoxValue<ValueType>(result);
|
|
}
|
|
|
|
const Object* GetCollectionObject()override
|
|
{
|
|
if constexpr (std::is_same_v<typename trait_helper::RemovePtr<T>::Type*, T>)
|
|
{
|
|
if (wrapperPointer->GetCollectionReference() == this)
|
|
{
|
|
return wrapperPointer;
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
};
|
|
|
|
#define KEY_VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyValueType
|
|
#define VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::ValueType
|
|
#define KEY_KEY_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyKeyType
|
|
|
|
template<typename T>
|
|
class ValueDictionaryWrapper : public virtual ValueReadonlyDictionaryWrapper<T>, public virtual IValueDictionary
|
|
{
|
|
public:
|
|
ValueDictionaryWrapper(const T& _wrapperPointer)
|
|
:ValueReadonlyDictionaryWrapper<T>(_wrapperPointer)
|
|
{
|
|
}
|
|
|
|
void Set(const Value& key, const Value& value)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
KEY_VALUE_TYPE item = UnboxValue<KEY_VALUE_TYPE>(key);
|
|
VALUE_TYPE result = UnboxValue<VALUE_TYPE>(value);
|
|
WRAPPER_POINTER->Set(item, result);
|
|
}
|
|
|
|
bool Remove(const Value& key)override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
KEY_KEY_TYPE item = UnboxValue<KEY_KEY_TYPE>(key);
|
|
return WRAPPER_POINTER->Remove(item);
|
|
}
|
|
|
|
void Clear()override
|
|
{
|
|
ENSURE_WRAPPER_POINTER;
|
|
WRAPPER_POINTER->Clear();
|
|
}
|
|
};
|
|
#undef KEY_VALUE_TYPE
|
|
#undef VALUE_TYPE
|
|
#undef KEY_KEY_TYPE
|
|
|
|
#undef ENSURE_WRAPPER_POINTER
|
|
#undef WRAPPER_POINTER
|
|
#pragma warning(pop)
|
|
}
|
|
}
|
|
|
|
namespace collections
|
|
{
|
|
template<typename T>
|
|
void ObservableList<T>::NotifyUpdateInternal(vint start, vint count, vint newCount)
|
|
{
|
|
if (auto colref = this->template TryGetCollectionReference<reflection::description::IValueObservableList>())
|
|
{
|
|
colref->ItemChanged(start, count, newCount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\BOXING\BOXINGPARAMETER_CONTAINERS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER_CONTAINERS
|
|
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER_CONTAINERS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Containers
|
|
***********************************************************************/
|
|
|
|
template<typename TValueItf, typename TExpectedItf, template<typename T> class TValueImpl, typename T>
|
|
auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t<std::is_convertible_v<TValueItf*, TExpectedItf*>, Ptr<TExpectedItf>>
|
|
{
|
|
auto colref = collection->template TryGetCollectionReference<TValueImpl<T*>>();
|
|
if (colref) return colref;
|
|
colref = Ptr(new TValueImpl<T*>(collection));
|
|
collection->SetCollectionReference(colref);
|
|
return colref;
|
|
}
|
|
|
|
template<typename TValueItf, typename TExpectedItf, template<typename T> class TValueImpl, typename T>
|
|
auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t<!std::is_convertible_v<TValueItf*, TExpectedItf*>, Ptr<TExpectedItf>>
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
throw ArgumentTypeMismtatchException(
|
|
WString::Unmanaged(L"collection"),
|
|
Description<TExpectedItf>::GetAssociatedTypeDescriptor(),
|
|
Description<TValueItf>::GetAssociatedTypeDescriptor()
|
|
);
|
|
#else
|
|
CHECK_FAIL(L"vl::reflection::description::GetValueCollectionFromCollection()#Argument type mismatch.");
|
|
#endif
|
|
}
|
|
|
|
template<typename TValueItf, typename T>
|
|
Ptr<TValueItf> ChooseValueCollectionFromNonDictionaryEnumerable(const collections::IEnumerable<T>* enumerable)
|
|
{
|
|
auto writable = const_cast<Object*>(enumerable->GetCollectionObject());
|
|
if (auto xs = dynamic_cast<collections::ObservableList<std::remove_cvref_t<T>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueObservableList, TValueItf, ValueObservableListWrapper>(xs);
|
|
}
|
|
else if (auto xs = dynamic_cast<collections::ObservableListBase<std::remove_cvref_t<T>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueList, TValueItf, ValueListWrapper>(xs);
|
|
}
|
|
else if (auto xs = dynamic_cast<collections::List<std::remove_cvref_t<T>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueList, TValueItf, ValueListWrapper>(xs);
|
|
}
|
|
else if (auto xs = dynamic_cast<collections::Array<std::remove_cvref_t<T>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueArray, TValueItf, ValueArrayWrapper>(xs);
|
|
}
|
|
else if (auto xs = dynamic_cast<collections::SortedList<std::remove_cvref_t<T>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueReadonlyList, TValueItf, ValueReadonlyListWrapper>(xs);
|
|
}
|
|
else
|
|
{
|
|
return GetValueCollectionFromCollection<IValueEnumerable, TValueItf, ValueEnumerableWrapper>(xs);
|
|
}
|
|
}
|
|
|
|
template<typename TValueItf, typename T>
|
|
Ptr<TValueItf> ChooseValueCollectionFromEnumerable(const collections::IEnumerable<T>* enumerable)
|
|
{
|
|
return ChooseValueCollectionFromNonDictionaryEnumerable<TValueItf>(enumerable);
|
|
}
|
|
|
|
template<typename TValueItf, typename K, typename V>
|
|
Ptr<TValueItf> ChooseValueCollectionFromEnumerable(const collections::IEnumerable<collections::Pair<K, V>>* enumerable)
|
|
{
|
|
auto writable = const_cast<Object*>(enumerable->GetCollectionObject());
|
|
if (auto xs = dynamic_cast<collections::Dictionary<std::remove_cvref_t<K>, std::remove_cvref_t<V>>*>(writable))
|
|
{
|
|
return GetValueCollectionFromCollection<IValueDictionary, TValueItf, ValueDictionaryWrapper>(xs);
|
|
}
|
|
else
|
|
{
|
|
return ChooseValueCollectionFromNonDictionaryEnumerable<TValueItf>(enumerable);
|
|
}
|
|
}
|
|
|
|
template<typename TValueItf, typename T>
|
|
Value GetValueFromEnumerable(const collections::IEnumerable<T>& enumerable)
|
|
{
|
|
auto result = ChooseValueCollectionFromEnumerable<TValueItf>(&enumerable);
|
|
ITypeDescriptor* td = nullptr;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
td = Description<TValueItf>::GetAssociatedTypeDescriptor();
|
|
#endif
|
|
return BoxValue(result, td);
|
|
}
|
|
|
|
template<typename T, typename TValueItf>
|
|
Unboxed<T> UnboxCollection(const Ptr<TValueItf>& colref)
|
|
{
|
|
using TCollection = std::remove_const_t<T>;
|
|
if (auto colobj = dynamic_cast<TCollection*>(const_cast<Object*>(colref->GetCollectionObject())))
|
|
{
|
|
return { colobj,false };
|
|
}
|
|
else
|
|
{
|
|
auto collection = new TCollection();
|
|
auto lazyList = GetLazyList<typename TCollection::ElementType>(colref);
|
|
collections::CopyFrom(*collection, lazyList);
|
|
return { collection, true };
|
|
}
|
|
}
|
|
|
|
template<typename T, typename TValueItf>
|
|
Unboxed<T> UnboxDictionary(const Ptr<TValueItf>& colref)
|
|
{
|
|
using TCollection = std::remove_const_t<T>;
|
|
if (auto colobj = dynamic_cast<TCollection*>(const_cast<Object*>(colref->GetCollectionObject())))
|
|
{
|
|
return { colobj,false };
|
|
}
|
|
else
|
|
{
|
|
auto collection = new TCollection();
|
|
auto lazyList = GetLazyList<
|
|
typename TCollection::KeyContainer::ElementType,
|
|
typename TCollection::ValueContainer::ElementType
|
|
>(colref);
|
|
collections::CopyFrom(*collection, lazyList);
|
|
return { collection, true };
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<const collections::LazyList<T>, TypeFlags::EnumerableType>
|
|
{
|
|
static Value BoxParameter(const collections::LazyList<T>& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
Ptr<IValueEnumerable> result = IValueEnumerable::Create(
|
|
collections::From(object)
|
|
.Select([](const T& item)
|
|
{
|
|
return BoxValue<T>(item);
|
|
})
|
|
);
|
|
|
|
ITypeDescriptor* td = nullptr;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
td = Description<IValueEnumerable>::GetAssociatedTypeDescriptor();
|
|
#endif
|
|
return BoxValue(result, td);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<collections::LazyList<T>, TypeFlags::EnumerableType>
|
|
{
|
|
static Value BoxParameter(collections::LazyList<T>& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return ParameterAccessor<const collections::LazyList<T>, TypeFlags::EnumerableType>::BoxParameter(object, typeDescriptor);
|
|
}
|
|
|
|
static Unboxed<collections::LazyList<T>> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
typedef typename collections::LazyList<T>::ElementType ElementType;
|
|
Ptr<IValueEnumerable> listProxy = UnboxValue<Ptr<IValueEnumerable>>(value, typeDescriptor, valueName);
|
|
return { new collections::LazyList<T>(std::move(GetLazyList<T>(listProxy))), true };
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::ReadonlyListType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueReadonlyList>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxCollection<T>(UnboxValue<Ptr<IValueReadonlyList>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::ArrayType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueArray>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxCollection<T>(UnboxValue<Ptr<IValueArray>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::ListType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueList>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxCollection<T>(UnboxValue<Ptr<IValueList>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::ObservableListType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueObservableList>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxCollection<T>(UnboxValue<Ptr<IValueObservableList>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::ReadonlyDictionaryType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueReadonlyDictionary>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxDictionary<T>(UnboxValue<Ptr<IValueReadonlyDictionary>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct ParameterAccessor<T, TypeFlags::DictionaryType>
|
|
{
|
|
static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
return GetValueFromEnumerable<IValueDictionary>(object);
|
|
}
|
|
|
|
static Unboxed<T> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
return UnboxDictionary<T>(UnboxValue<Ptr<IValueDictionary>>(value, typeDescriptor, valueName));
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\WRAPPERS\FUNCTIONWRAPPERS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_WRAPPERS_FUNCTIONWRAPPERS
|
|
#define VCZH_REFLECTION_WRAPPERS_FUNCTIONWRAPPERS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Function Wrappers
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class ValueFunctionProxyWrapper
|
|
{
|
|
};
|
|
|
|
template<typename R, typename ...TArgs>
|
|
class ValueFunctionProxyWrapper<R(TArgs...)> : public Object, public virtual IValueFunctionProxy
|
|
{
|
|
typedef Func<R(TArgs...)> FunctionType;
|
|
protected:
|
|
FunctionType function;
|
|
|
|
public:
|
|
ValueFunctionProxyWrapper(const FunctionType& _function)
|
|
:function(_function)
|
|
{
|
|
}
|
|
|
|
FunctionType GetFunction()
|
|
{
|
|
return function;
|
|
}
|
|
|
|
Value Invoke(Ptr<IValueReadonlyList> arguments)override
|
|
{
|
|
if (!arguments || arguments->GetCount() != sizeof...(TArgs))
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
throw ArgumentCountMismtatchException();
|
|
#else
|
|
CHECK_FAIL(L"Argument count mismatch.");
|
|
#endif
|
|
}
|
|
return invoke_helper::InvokeObject<FunctionType, TArgs...>(function, nullptr, arguments);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\BOXING\BOXINGPARAMETER_FUNCTIONS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_BOXINGPARAMETER_FUNCTIONS
|
|
#define VCZH_REFLECTION_BOXING_BOXINGPARAMETER_FUNCTIONS
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
Functions
|
|
***********************************************************************/
|
|
|
|
template<typename R, typename ...TArgs>
|
|
struct ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
|
|
{
|
|
static Value BoxParameter(const Func<R(TArgs...)>& object, ITypeDescriptor* typeDescriptor)
|
|
{
|
|
typedef R(RawFunctionType)(TArgs...);
|
|
Ptr<IValueFunctionProxy> result=Ptr(new ValueFunctionProxyWrapper<RawFunctionType>(object));
|
|
|
|
ITypeDescriptor* td = nullptr;
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
td = Description<IValueFunctionProxy>::GetAssociatedTypeDescriptor();
|
|
#endif
|
|
return BoxValue<Ptr<IValueFunctionProxy>>(result, td);
|
|
}
|
|
|
|
static Unboxed<Func<R(TArgs...)>> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName)
|
|
{
|
|
typedef R(RawFunctionType)(TArgs...);
|
|
typedef Func<R(TArgs...)> FunctionType;
|
|
typedef ValueFunctionProxyWrapper<RawFunctionType> ProxyType;
|
|
if (auto functionProxy = UnboxValue<Ptr<IValueFunctionProxy>>(value, typeDescriptor, valueName))
|
|
{
|
|
if (auto proxy = functionProxy.Cast<ProxyType>())
|
|
{
|
|
return { new FunctionType(std::move(proxy->GetFunction())), true };
|
|
}
|
|
else
|
|
{
|
|
return { new FunctionType([functionProxy](TArgs ...args)
|
|
{
|
|
Ptr<IValueList> arguments = IValueList::Create();
|
|
BoxParametersToList(arguments, std::forward<TArgs>(args)...);
|
|
auto result = functionProxy->Invoke(arguments);
|
|
if constexpr (!std::is_same_v<R, void>)
|
|
{
|
|
auto unboxed = description::UnboxParameter<std::remove_cvref_t<R>>(result);
|
|
if (std::is_reference_v<R>)
|
|
{
|
|
CHECK_ERROR(!unboxed.IsOwned(), L"It is impossible to return a reference from a unboxed value, when the unboxing has to call new T(...).");
|
|
}
|
|
return unboxed.Ref();
|
|
}
|
|
}), true };
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return { new FunctionType(),true };
|
|
}
|
|
}
|
|
};
|
|
|
|
template<typename R, typename ...TArgs>
|
|
struct ParameterAccessor<const Func<R(TArgs...)>, TypeFlags::FunctionType> : ParameterAccessor<Func<R(TArgs...)>, TypeFlags::FunctionType>
|
|
{
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\BOXING\BOXING.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_BOXING_BOXING
|
|
#define VCZH_REFLECTION_BOXING_BOXING
|
|
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\METADATA\METADATA_MEMBER.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_METADATA_METADATA_MEMBER
|
|
#define VCZH_REFLECTION_METADATA_METADATA_MEMBER
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
/***********************************************************************
|
|
ConstructorArgumentAdder
|
|
***********************************************************************/
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
namespace internal_helper
|
|
{
|
|
template<typename T>
|
|
struct ConstructorArgumentAdder
|
|
{
|
|
static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
|
|
{
|
|
}
|
|
};
|
|
|
|
template<typename T0, typename ...TNextArgs>
|
|
struct ConstructorArgumentAdder<TypeTuple<T0, TNextArgs...>>
|
|
{
|
|
static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index)
|
|
{
|
|
methodInfo->AddParameter(Ptr(new ParameterInfoImpl(methodInfo, parameterNames[index], TypeInfoRetriver<T0>::CreateTypeInfo())));
|
|
ConstructorArgumentAdder<TypeTuple<TNextArgs...>>::Add(methodInfo, parameterNames, index + 1);
|
|
}
|
|
};
|
|
}
|
|
|
|
/***********************************************************************
|
|
MethodInfoImpl
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
class CustomConstructorInfoImpl{};
|
|
|
|
template<typename TClass, typename T>
|
|
class CustomMethodInfoImpl{};
|
|
|
|
template<typename TClass, typename T>
|
|
class CustomExternalMethodInfoImpl{};
|
|
|
|
template<typename T>
|
|
class CustomStaticMethodInfoImpl{};
|
|
|
|
template<typename TClass, typename T>
|
|
class CustomEventInfoImpl{};
|
|
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\METADATA\METADATA_EVENT.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_METADATA_METADATA_EVENT
|
|
#define VCZH_REFLECTION_METADATA_METADATA_EVENT
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
template<typename ...TArgs>
|
|
struct EventHelper
|
|
{
|
|
using Handler = const Func<void(TArgs...)>&;
|
|
|
|
class EventHandlerImpl : public Object, public reflection::description::IEventHandler
|
|
{
|
|
public:
|
|
Ptr<EventHandler> handler;
|
|
|
|
EventHandlerImpl(Ptr<EventHandler> _handler)
|
|
:handler(_handler)
|
|
{
|
|
}
|
|
|
|
bool IsAttached()override
|
|
{
|
|
return handler->IsAttached();
|
|
}
|
|
};
|
|
|
|
static Ptr<reflection::description::IEventHandler> Attach(Event<void(TArgs...)>& e, Handler handler)
|
|
{
|
|
return Ptr(new EventHandlerImpl(e.Add(handler)));
|
|
}
|
|
|
|
static bool Detach(Event<void(TArgs...)>& e, Ptr<reflection::description::IEventHandler> handler)
|
|
{
|
|
auto impl = handler.Cast<EventHandlerImpl>();
|
|
if (!impl) return false;
|
|
return e.Remove(impl->handler);
|
|
}
|
|
|
|
static Event<void(TArgs...)>& Invoke(Event<void(TArgs...)>& e)
|
|
{
|
|
return e;
|
|
}
|
|
};
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
/***********************************************************************
|
|
CustomEventInfoImpl<void(TArgs...)>
|
|
***********************************************************************/
|
|
|
|
template<typename TClass, typename ...TArgs>
|
|
class CustomEventInfoImpl<TClass, void(TArgs...)> : public EventInfoImpl
|
|
{
|
|
protected:
|
|
Event<void(TArgs...)> TClass::* eventRef;
|
|
|
|
Ptr<IEventHandler> AttachInternal(DescriptableObject* thisObject, Ptr<IValueFunctionProxy> handler)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
|
|
Event<void(TArgs...)>& eventObject = object->*eventRef;
|
|
auto func = Func<void(TArgs...)>([=](TArgs ...args)
|
|
{
|
|
auto arguments = IValueList::Create();
|
|
BoxParametersToList(arguments, std::forward<TArgs>(args)...);
|
|
handler->Invoke(arguments);
|
|
});
|
|
return EventHelper<TArgs...>::Attach(eventObject, func);
|
|
}
|
|
|
|
bool DetachInternal(DescriptableObject* thisObject, Ptr<IEventHandler> handler)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
|
|
Event<void(TArgs...)>& eventObject = object->*eventRef;
|
|
return EventHelper<TArgs...>::Detach(eventObject, handler);
|
|
}
|
|
|
|
void InvokeInternal(DescriptableObject* thisObject, Ptr<IValueReadonlyList> arguments)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject");
|
|
Event<void(TArgs...)>& eventObject = object->*eventRef;
|
|
invoke_helper::InvokeObject<Event<void(TArgs...)>, TArgs...>(eventObject, nullptr, arguments);
|
|
}
|
|
|
|
Ptr<ITypeInfo> GetHandlerTypeInternal()override
|
|
{
|
|
return TypeInfoRetriver<Func<void(TArgs...)>>::CreateTypeInfo();
|
|
}
|
|
public:
|
|
CustomEventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Event<void(TArgs...)> TClass::* _eventRef)
|
|
:EventInfoImpl(_ownerTypeDescriptor, _name)
|
|
, eventRef(_eventRef)
|
|
{
|
|
}
|
|
|
|
~CustomEventInfoImpl()
|
|
{
|
|
}
|
|
|
|
IEventInfo::ICpp* GetCpp()override
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct CustomEventFunctionTypeRetriver
|
|
{
|
|
typedef vint Type;
|
|
};
|
|
|
|
template<typename TClass, typename TEvent>
|
|
struct CustomEventFunctionTypeRetriver<Event<TEvent> TClass::*>
|
|
{
|
|
typedef TEvent Type;
|
|
};
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\METADATA\METADATA_FUNCTION.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_METADATA_METADATA_FUNCTION
|
|
#define VCZH_REFLECTION_METADATA_METADATA_FUNCTION
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
/***********************************************************************
|
|
CustomConstructorInfoImpl<R(TArgs...)>
|
|
***********************************************************************/
|
|
|
|
template<typename R, typename ...TArgs>
|
|
class CustomConstructorInfoImpl<R(TArgs...)> : public MethodInfoImpl
|
|
{
|
|
using TClass = typename trait_helper::RemovePtr<std::remove_cvref_t<R>>::Type;
|
|
protected:
|
|
|
|
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
|
|
{
|
|
return BoxParameter(unboxcall_helper::Unbox<MakeArgPacks<TArgs...>>::template AndNew<TClass, R>(this, arguments));
|
|
}
|
|
|
|
Value CreateFunctionProxyInternal(const Value& thisObject)override
|
|
{
|
|
auto proxy = Func([](TArgs ...args)->R
|
|
{
|
|
R result = R(new TClass(args...));
|
|
return result;
|
|
});
|
|
return BoxParameter(proxy);
|
|
}
|
|
public:
|
|
CustomConstructorInfoImpl(const wchar_t* parameterNames[])
|
|
:MethodInfoImpl(0, TypeInfoRetriver<R>::CreateTypeInfo(), true)
|
|
{
|
|
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
|
|
}
|
|
|
|
IMethodInfo::ICpp* GetCpp()override
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
CustomMethodInfoImpl<TClass, R(TArgs...)>
|
|
CustomExternalMethodInfoImpl<TClass, R(TArgs...)>
|
|
***********************************************************************/
|
|
|
|
class MethodInfoImpl_StaticCpp : public MethodInfoImpl, private IMethodInfo::ICpp
|
|
{
|
|
private:
|
|
WString invokeTemplate;
|
|
WString closureTemplate;
|
|
|
|
const WString& GetInvokeTemplate()override
|
|
{
|
|
return invokeTemplate;
|
|
}
|
|
|
|
const WString& GetClosureTemplate()override
|
|
{
|
|
return closureTemplate;
|
|
}
|
|
public:
|
|
MethodInfoImpl_StaticCpp(IMethodGroupInfo* _ownerMethodGroup, Ptr<ITypeInfo> _return, bool _isStatic, const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
|
|
:MethodInfoImpl(_ownerMethodGroup, _return, _isStatic)
|
|
{
|
|
CHECK_ERROR((_invokeTemplate == nullptr) == (_closureTemplate == nullptr), L"MethodInfoImpl_StaticCpp::MethodInfoImpl_StaticCpp()#Templates should all be set or default at the same time.");
|
|
if (_invokeTemplate)
|
|
{
|
|
invokeTemplate = WString::Unmanaged(_invokeTemplate);
|
|
}
|
|
if (_closureTemplate)
|
|
{
|
|
closureTemplate = WString::Unmanaged(_closureTemplate);
|
|
}
|
|
}
|
|
|
|
IMethodInfo::ICpp* GetCpp()override
|
|
{
|
|
return invokeTemplate.Length() == 0 || closureTemplate.Length() == 0 ? nullptr : this;
|
|
}
|
|
};
|
|
|
|
template<typename TClass, typename R, typename ...TArgs>
|
|
class CustomMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
|
|
{
|
|
protected:
|
|
R(__thiscall TClass::* method)(TArgs...);
|
|
|
|
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
|
|
return invoke_helper::InvokeMethod<TClass, R, TArgs...>(object, method, this, arguments);
|
|
}
|
|
|
|
Value CreateFunctionProxyInternal(const Value& thisObject)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
|
|
Func<R(TArgs...)> proxy(object, method);
|
|
return BoxParameter(proxy);
|
|
}
|
|
public:
|
|
CustomMethodInfoImpl(const wchar_t* parameterNames[], R(__thiscall TClass::* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
|
|
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
|
|
, method(_method)
|
|
{
|
|
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
|
|
}
|
|
};
|
|
|
|
template<typename TClass, typename R, typename ...TArgs>
|
|
class CustomExternalMethodInfoImpl<TClass, R(TArgs...)> : public MethodInfoImpl_StaticCpp
|
|
{
|
|
protected:
|
|
R(*method)(TClass*, TArgs...);
|
|
|
|
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
|
|
return invoke_helper::InvokeExternal<TClass, R, TArgs...>(object, method, this, arguments);
|
|
}
|
|
|
|
Value CreateFunctionProxyInternal(const Value& thisObject)override
|
|
{
|
|
TClass* object = UnboxValue<TClass*>(thisObject, GetOwnerTypeDescriptor(), L"thisObject");
|
|
auto proxy = Func([object, this](TArgs... args)->decltype(auto) { return method(object, args...); });
|
|
return BoxParameter(proxy);
|
|
}
|
|
public:
|
|
CustomExternalMethodInfoImpl(const wchar_t* parameterNames[], R(*_method)(TClass*, TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
|
|
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate)
|
|
, method(_method)
|
|
{
|
|
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
CustomStaticMethodInfoImpl<R(TArgs...)>
|
|
***********************************************************************/
|
|
|
|
template<typename R, typename ...TArgs>
|
|
class CustomStaticMethodInfoImpl<R(TArgs...)> : public MethodInfoImpl_StaticCpp
|
|
{
|
|
protected:
|
|
R(* method)(TArgs...);
|
|
|
|
Value InvokeInternal(const Value& thisObject, collections::Array<Value>& arguments)override
|
|
{
|
|
return invoke_helper::InvokeFunction<R, TArgs...>(method, this, arguments);
|
|
}
|
|
|
|
Value CreateFunctionProxyInternal(const Value& thisObject)override
|
|
{
|
|
Func<R(TArgs...)> proxy(method);
|
|
return BoxParameter(proxy);
|
|
}
|
|
public:
|
|
CustomStaticMethodInfoImpl(const wchar_t* parameterNames[], R(* _method)(TArgs...), const wchar_t* _invokeTemplate, const wchar_t* _closureTemplate)
|
|
:MethodInfoImpl_StaticCpp(0, TypeInfoRetriver<R>::CreateTypeInfo(), true, _invokeTemplate, _closureTemplate)
|
|
,method(_method)
|
|
{
|
|
internal_helper::ConstructorArgumentAdder<TypeTuple<TArgs...>>::Add(this, parameterNames, 0);
|
|
}
|
|
};
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
.\REFLECTION\MACROS.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_REFLECTION_MACROS
|
|
#define VCZH_REFLECTION_REFLECTION_MACROS
|
|
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
/***********************************************************************
|
|
Macros
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
template<typename T>
|
|
struct CustomTypeDescriptorSelector{};
|
|
|
|
struct MethodPointerBinaryData
|
|
{
|
|
typedef collections::Dictionary<MethodPointerBinaryData, IMethodInfo*> MethodMap;
|
|
|
|
class IIndexer : public virtual IDescriptable
|
|
{
|
|
public:
|
|
virtual void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo) = 0;
|
|
virtual IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data) = 0;
|
|
};
|
|
|
|
vint data[4];
|
|
|
|
friend std::strong_ordering operator<=>(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
|
|
{
|
|
for (vint i = 0; i < sizeof(data) / sizeof(*data); i++)
|
|
{
|
|
auto result = a.data[i] <=> b.data[i];
|
|
if (result != 0) return result;
|
|
}
|
|
return std::strong_ordering::equal;
|
|
}
|
|
|
|
friend bool operator==(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b)
|
|
{
|
|
return (a <=> b) == 0;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
union MethodPointerBinaryDataRetriver
|
|
{
|
|
T methodPointer;
|
|
MethodPointerBinaryData binaryData;
|
|
|
|
MethodPointerBinaryDataRetriver(T _methodPointer)
|
|
{
|
|
memset(&binaryData, 0, sizeof(binaryData));
|
|
methodPointer = _methodPointer;
|
|
}
|
|
|
|
const MethodPointerBinaryData& GetBinaryData()
|
|
{
|
|
static_assert(sizeof(T) <= sizeof(MethodPointerBinaryData), "Your C++ compiler is bad!");
|
|
return binaryData;
|
|
}
|
|
};
|
|
|
|
template<typename T, TypeDescriptorFlags TDFlags>
|
|
struct MethodPointerBinaryDataRecorder
|
|
{
|
|
static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
|
|
{
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct MethodPointerBinaryDataRecorder<T, TypeDescriptorFlags::Interface>
|
|
{
|
|
static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo)
|
|
{
|
|
auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(td);
|
|
CHECK_ERROR(impl != nullptr, L"Internal error: RecordMethod can only be called when registering methods.");
|
|
impl->IndexMethodInfo(data, methodInfo);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
using FUNCTIONNAME_AddPointer = T*;
|
|
|
|
/***********************************************************************
|
|
Type
|
|
***********************************************************************/
|
|
|
|
#define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{
|
|
#define END_TYPE_INFO_NAMESPACE }}}
|
|
#define ADD_TYPE_INFO(TYPENAME)\
|
|
{\
|
|
auto type = Ptr(new CustomTypeDescriptorSelector<TYPENAME>::CustomTypeDescriptorImpl());\
|
|
manager->SetTypeDescriptor(TypeInfo<TYPENAME>::content.typeName, type);\
|
|
}
|
|
|
|
/***********************************************************************
|
|
InterfaceProxy
|
|
***********************************************************************/
|
|
|
|
#define INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
|
|
static INTERFACE* Create(Ptr<IValueInterfaceProxy> proxy)\
|
|
{\
|
|
auto obj = new ValueInterfaceProxy<INTERFACE>();\
|
|
obj->SetProxy(proxy);\
|
|
return obj;\
|
|
}\
|
|
|
|
#define INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
|
|
static Ptr<INTERFACE> Create(Ptr<IValueInterfaceProxy> proxy)\
|
|
{\
|
|
auto obj = Ptr(new ValueInterfaceProxy<INTERFACE>());\
|
|
obj->SetProxy(proxy);\
|
|
return obj;\
|
|
}\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
|
|
template<>\
|
|
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE>\
|
|
{\
|
|
typedef INTERFACE _interface_proxy_InterfaceType;\
|
|
public:\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(INTERFACE)\
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
|
|
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(INTERFACE)\
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
|
|
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, ...)\
|
|
template<>\
|
|
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE, __VA_ARGS__>\
|
|
{\
|
|
typedef INTERFACE _interface_proxy_InterfaceType;\
|
|
public:\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_RAWPTR(INTERFACE, ...)\
|
|
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
|
|
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
|
|
|
|
#define BEGIN_INTERFACE_PROXY_SHAREDPTR(INTERFACE, ...)\
|
|
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
|
|
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
|
|
|
|
#define END_INTERFACE_PROXY(INTERFACE)\
|
|
};
|
|
|
|
/***********************************************************************
|
|
InterfaceProxy::Invoke
|
|
***********************************************************************/
|
|
|
|
template<typename TClass, typename TReturn, typename ...TArgument>
|
|
auto MethodTypeTrait(TArgument...)->TReturn(TClass::*)(TArgument...)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
#define PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
|
|
static ITypeDescriptor* _interface_proxy_typeDescriptor = nullptr;\
|
|
static IMethodInfo* _interface_proxy_methodInfo = nullptr;\
|
|
if (_interface_proxy_typeDescriptor != static_cast<DescriptableObject*>(this)->GetTypeDescriptor())\
|
|
{\
|
|
_interface_proxy_typeDescriptor = static_cast<DescriptableObject*>(this)->GetTypeDescriptor();\
|
|
CHECK_ERROR(_interface_proxy_typeDescriptor != nullptr, L"Internal error: The type of this interface has not been registered.");\
|
|
auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(_interface_proxy_typeDescriptor);\
|
|
CHECK_ERROR(impl != nullptr, L"Internal error: BEGIN_INTERFACE_PROXY is the only correct way to register an interface with a proxy.");\
|
|
auto _interface_proxy_method\
|
|
= (decltype(MethodTypeTrait<_interface_proxy_InterfaceType, decltype(METHODNAME(__VA_ARGS__))>(__VA_ARGS__)))\
|
|
&_interface_proxy_InterfaceType::METHODNAME;\
|
|
MethodPointerBinaryDataRetriver<decltype(_interface_proxy_method)> binaryData(_interface_proxy_method);\
|
|
_interface_proxy_methodInfo = impl->GetIndexedMethodInfo(binaryData.GetBinaryData());\
|
|
}\
|
|
|
|
#define INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
|
|
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
|
|
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))
|
|
|
|
#define INVOKE_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
|
|
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
|
|
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())
|
|
|
|
#define INVOKEGET_INTERFACE_PROXY(METHODNAME, ...)\
|
|
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
|
|
return UnboxParameter<decltype(METHODNAME(__VA_ARGS__))>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))).Ref()
|
|
|
|
#define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
|
|
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
|
|
return UnboxParameter<decltype(METHODNAME())>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())).Ref()
|
|
|
|
/***********************************************************************
|
|
Enum
|
|
***********************************************************************/
|
|
|
|
#define BEGIN_ENUM_ITEM_FLAG(TYPENAME, TDFLAGS)\
|
|
template<>\
|
|
struct CustomTypeDescriptorSelector<TYPENAME>\
|
|
{\
|
|
public:\
|
|
class CustomTypeDescriptorImpl : public EnumTypeDescriptor<TYPENAME, TDFLAGS>\
|
|
{\
|
|
typedef TYPENAME EnumType;\
|
|
public:\
|
|
void LoadInternal()override\
|
|
{\
|
|
EnumTypeDescriptor<TYPENAME, TDFLAGS>::LoadInternal();\
|
|
|
|
#define BEGIN_ENUM_ITEM(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::NormalEnum)
|
|
#define BEGIN_ENUM_ITEM_MERGABLE(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::FlagEnum)
|
|
|
|
#define END_ENUM_ITEM(TYPENAME)\
|
|
}\
|
|
};\
|
|
};
|
|
|
|
#define ENUM_ITEM_NAMESPACE(TYPENAME) typedef TYPENAME EnumItemNamespace;
|
|
#define ENUM_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, ITEMNAME);
|
|
#define ENUM_NAMESPACE_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumItemNamespace::ITEMNAME);
|
|
#define ENUM_CLASS_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumType::ITEMNAME);
|
|
|
|
/***********************************************************************
|
|
Struct
|
|
***********************************************************************/
|
|
|
|
#define BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TDFLAGS)\
|
|
template<>\
|
|
struct CustomTypeDescriptorSelector<TYPENAME>\
|
|
{\
|
|
public:\
|
|
class CustomTypeDescriptorImpl : public StructTypeDescriptor<TYPENAME, TDFLAGS>\
|
|
{\
|
|
typedef TYPENAME StructType;\
|
|
protected:\
|
|
void LoadInternal()override\
|
|
{
|
|
|
|
#define BEGIN_STRUCT_MEMBER(TYPENAME)\
|
|
BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TypeDescriptorFlags::Struct)
|
|
|
|
#define END_STRUCT_MEMBER(TYPENAME)\
|
|
}\
|
|
};\
|
|
};
|
|
|
|
#define STRUCT_MEMBER(FIELDNAME)\
|
|
fields.Add(L ## #FIELDNAME, Ptr(new StructFieldInfo<decltype(((StructType*)0)->FIELDNAME)>(this, &StructType::FIELDNAME, L ## #FIELDNAME)));
|
|
|
|
/***********************************************************************
|
|
Class
|
|
***********************************************************************/
|
|
|
|
#define BEGIN_CLASS_MEMBER(TYPENAME)\
|
|
template<>\
|
|
struct CustomTypeDescriptorSelector<TYPENAME>\
|
|
{\
|
|
public:\
|
|
class CustomTypeDescriptorImpl : public TypeDescriptorImpl\
|
|
{\
|
|
typedef TYPENAME ClassType;\
|
|
static const TypeDescriptorFlags TDFlags = TypeDescriptorFlags::Class;\
|
|
public:\
|
|
CustomTypeDescriptorImpl()\
|
|
:TypeDescriptorImpl(TDFlags, &TypeInfo<TYPENAME>::content)\
|
|
{\
|
|
Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
|
|
}\
|
|
~CustomTypeDescriptorImpl()\
|
|
{\
|
|
Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
|
|
}\
|
|
protected:\
|
|
bool IsAggregatable()override\
|
|
{\
|
|
return std::is_convertible_v<TYPENAME*, AggregatableDescription<TYPENAME>*>;\
|
|
}\
|
|
void LoadInternal()override\
|
|
{
|
|
|
|
#define CLASS_MEMBER_BASE(TYPENAME)\
|
|
AddBaseType(description::GetTypeDescriptor<TYPENAME>());
|
|
|
|
#define END_CLASS_MEMBER(TYPENAME)\
|
|
if (GetBaseTypeDescriptorCount() == 0) CLASS_MEMBER_BASE(DescriptableObject)\
|
|
}\
|
|
};\
|
|
};
|
|
|
|
/***********************************************************************
|
|
Interface
|
|
***********************************************************************/
|
|
|
|
#define BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TDFLAGS)\
|
|
template<>\
|
|
struct CustomTypeDescriptorSelector<TYPENAME>\
|
|
{\
|
|
public:\
|
|
class CustomTypeDescriptorImpl : public TypeDescriptorImpl, public MethodPointerBinaryData::IIndexer\
|
|
{\
|
|
typedef TYPENAME ClassType;\
|
|
static const TypeDescriptorFlags TDFlags = TDFLAGS;\
|
|
MethodPointerBinaryData::MethodMap methodsForProxy;\
|
|
public:\
|
|
CustomTypeDescriptorImpl()\
|
|
:TypeDescriptorImpl(TDFLAGS, &TypeInfo<TYPENAME>::content)\
|
|
{\
|
|
Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
|
|
}\
|
|
~CustomTypeDescriptorImpl()\
|
|
{\
|
|
Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
|
|
}\
|
|
void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo)override\
|
|
{\
|
|
methodsForProxy.Add(data, methodInfo);\
|
|
}\
|
|
IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data)override\
|
|
{\
|
|
Load();\
|
|
return methodsForProxy[data];\
|
|
}\
|
|
protected:\
|
|
void LoadInternal()override\
|
|
{
|
|
|
|
#define BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TypeDescriptorFlags::Interface)
|
|
|
|
#define BEGIN_INTERFACE_MEMBER(TYPENAME)\
|
|
BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
|
|
CLASS_MEMBER_EXTERNALCTOR(decltype(ValueInterfaceProxy<TYPENAME>::Create(nullptr))(Ptr<IValueInterfaceProxy>), { L"proxy" }, vl::reflection::description::ValueInterfaceProxy<TYPENAME>::Create)
|
|
|
|
#define END_INTERFACE_MEMBER(TYPENAME)\
|
|
if (GetBaseTypeDescriptorCount() == 0 && TDFlags == TypeDescriptorFlags::Interface) CLASS_MEMBER_BASE(IDescriptable)\
|
|
}\
|
|
};\
|
|
};
|
|
|
|
/***********************************************************************
|
|
Field
|
|
***********************************************************************/
|
|
|
|
#define CLASS_MEMBER_FIELD(FIELDNAME)\
|
|
AddProperty(\
|
|
Ptr(new CustomFieldInfoImpl<\
|
|
ClassType,\
|
|
decltype(((ClassType*)0)->FIELDNAME)\
|
|
>(this, L ## #FIELDNAME, &ClassType::FIELDNAME)\
|
|
));
|
|
|
|
/***********************************************************************
|
|
Constructor
|
|
***********************************************************************/
|
|
|
|
#define NO_PARAMETER {L""}
|
|
#define PROTECT_PARAMETERS(...) __VA_ARGS__
|
|
|
|
#define CLASS_MEMBER_CONSTRUCTOR(FUNCTIONTYPE, PARAMETERNAMES)\
|
|
{\
|
|
const wchar_t* parameterNames[]=PARAMETERNAMES;\
|
|
AddConstructor(Ptr(new CustomConstructorInfoImpl<FUNCTIONTYPE>(parameterNames)));\
|
|
}
|
|
|
|
#define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
|
|
{\
|
|
const wchar_t* parameterNames[]=PARAMETERNAMES;\
|
|
AddConstructor(\
|
|
Ptr(new CustomStaticMethodInfoImpl<FUNCTIONTYPE>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
|
|
);\
|
|
}
|
|
|
|
#define CLASS_MEMBER_EXTERNALCTOR(FUNCTIONTYPE, PARAMETERNAMES, SOURCE)\
|
|
CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PROTECT_PARAMETERS(PARAMETERNAMES), (FUNCTIONNAME_AddPointer<FUNCTIONTYPE>)&::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
|
|
|
|
/***********************************************************************
|
|
Method
|
|
***********************************************************************/
|
|
|
|
#define CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
|
|
{\
|
|
const wchar_t* parameterNames[]=PARAMETERNAMES;\
|
|
AddMethod(\
|
|
L ## #FUNCTIONNAME,\
|
|
Ptr(new CustomExternalMethodInfoImpl<\
|
|
ClassType,\
|
|
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
|
|
>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
|
|
);\
|
|
}
|
|
|
|
#define CLASS_MEMBER_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
|
|
CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($This, $Arguments)", L"::vl::Func<$Func>($This, &::" L ## #SOURCE L")")
|
|
|
|
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, INVOKETEMPLATE, CLOSURETEMPLATE)\
|
|
{\
|
|
const wchar_t* parameterNames[]=PARAMETERNAMES;\
|
|
auto methodInfo = Ptr(new CustomMethodInfoImpl<\
|
|
ClassType,\
|
|
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
|
|
>\
|
|
(parameterNames, (FUNCTIONTYPE)&ClassType::FUNCTIONNAME, INVOKETEMPLATE, CLOSURETEMPLATE));\
|
|
AddMethod(\
|
|
L ## #EXPECTEDNAME,\
|
|
methodInfo\
|
|
);\
|
|
MethodPointerBinaryDataRetriver<FUNCTIONTYPE> binaryDataRetriver(&ClassType::FUNCTIONNAME);\
|
|
MethodPointerBinaryDataRecorder<ClassType, TDFlags>::RecordMethod(binaryDataRetriver.GetBinaryData(), this, methodInfo.Obj());\
|
|
}
|
|
|
|
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
|
|
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, L"$This->" L ## #FUNCTIONNAME L"($Arguments)", L"::vl::Func<$Func>($This, &$Type::" L ## #FUNCTIONNAME L")")
|
|
|
|
#define CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
|
|
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(FUNCTIONNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, nullptr, nullptr)
|
|
|
|
#define CLASS_MEMBER_METHOD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES)\
|
|
CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
|
|
|
|
#define CLASS_MEMBER_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
|
|
CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
|
|
|
|
/***********************************************************************
|
|
Static Method
|
|
***********************************************************************/
|
|
|
|
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
|
|
{\
|
|
const wchar_t* parameterNames[]=PARAMETERNAMES;\
|
|
AddMethod(\
|
|
L ## #FUNCTIONNAME,\
|
|
Ptr(new CustomStaticMethodInfoImpl<\
|
|
std::remove_pointer_t<FUNCTIONTYPE>\
|
|
>(parameterNames, (FUNCTIONTYPE)SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE))\
|
|
);\
|
|
}
|
|
|
|
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
|
|
|
|
#define CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
|
|
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &ClassType::FUNCTIONNAME, nullptr, nullptr)
|
|
|
|
#define CLASS_MEMBER_STATIC_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
|
|
CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
|
|
|
|
/***********************************************************************
|
|
Event
|
|
***********************************************************************/
|
|
|
|
#define CLASS_MEMBER_EVENT(EVENTNAME)\
|
|
AddEvent(\
|
|
Ptr(new CustomEventInfoImpl<\
|
|
ClassType,\
|
|
CustomEventFunctionTypeRetriver<decltype(&ClassType::EVENTNAME)>::Type\
|
|
>(this, L ## #EVENTNAME, &ClassType::EVENTNAME))\
|
|
);
|
|
|
|
/***********************************************************************
|
|
Property
|
|
***********************************************************************/
|
|
|
|
#define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\
|
|
AddProperty(\
|
|
Ptr(new PropertyInfoImpl(\
|
|
this,\
|
|
L ## #PROPERTYNAME,\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
|
|
nullptr,\
|
|
nullptr\
|
|
))\
|
|
);
|
|
|
|
#define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\
|
|
AddProperty(\
|
|
Ptr(new PropertyInfoImpl(\
|
|
this,\
|
|
L ## #PROPERTYNAME,\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
|
|
nullptr\
|
|
))\
|
|
);
|
|
|
|
#define CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, GETTER, SETTER, EVENT)\
|
|
AddProperty(\
|
|
Ptr(new PropertyInfoImpl(\
|
|
this,\
|
|
L ## #PROPERTYNAME,\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
|
|
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
|
|
))\
|
|
);
|
|
|
|
#define CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, GETTER, EVENT)\
|
|
AddProperty(\
|
|
Ptr(new PropertyInfoImpl(\
|
|
this,\
|
|
L ## #PROPERTYNAME,\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
|
|
nullptr,\
|
|
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
|
|
))\
|
|
);
|
|
|
|
#define CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE(PROPERTYNAME, GETTER, SETTER, REFERENCETEMPLATE)\
|
|
AddProperty(\
|
|
Ptr(new PropertyInfoImpl_StaticCpp(\
|
|
this,\
|
|
L ## #PROPERTYNAME,\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
|
|
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
|
|
nullptr,\
|
|
WString::Unmanaged(REFERENCETEMPLATE)\
|
|
))\
|
|
);
|
|
|
|
#define CLASS_MEMBER_PROPERTY_READONLY_FAST(PROPERTYNAME)\
|
|
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
|
|
CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, Get##PROPERTYNAME)\
|
|
|
|
#define CLASS_MEMBER_PROPERTY_FAST(PROPERTYNAME)\
|
|
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
|
|
CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
|
|
CLASS_MEMBER_PROPERTY(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME)\
|
|
|
|
#define CLASS_MEMBER_PROPERTY_EVENT_FAST(PROPERTYNAME, EVENTNAME)\
|
|
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
|
|
CLASS_MEMBER_METHOD(Set##PROPERTYNAME, {L"value"})\
|
|
CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, Get##PROPERTYNAME, Set##PROPERTYNAME, EVENTNAME)\
|
|
|
|
#define CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(PROPERTYNAME, EVENTNAME)\
|
|
CLASS_MEMBER_METHOD(Get##PROPERTYNAME, NO_PARAMETER)\
|
|
CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, Get##PROPERTYNAME, EVENTNAME)\
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\REFLECTION\REFLECTION.H
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
Author: Zihan Chen (vczh)
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_REFLECTION_REFLECTION_REFLECTION
|
|
#define VCZH_REFLECTION_REFLECTION_REFLECTION
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace reflection
|
|
{
|
|
namespace description
|
|
{
|
|
|
|
/***********************************************************************
|
|
Predefined Types
|
|
***********************************************************************/
|
|
|
|
#define REFLECTION_PREDEFINED_PRIMITIVE_TYPES(F)\
|
|
F(vuint8_t) \
|
|
F(vuint16_t) \
|
|
F(vuint32_t) \
|
|
F(vuint64_t) \
|
|
F(vint8_t) \
|
|
F(vint16_t) \
|
|
F(vint32_t) \
|
|
F(vint64_t) \
|
|
F(float) \
|
|
F(double) \
|
|
F(bool) \
|
|
F(wchar_t) \
|
|
F(WString) \
|
|
F(Locale) \
|
|
|
|
#define REFLECTION_PREDEFINED_SERIALIZABLE_TYPES(F)\
|
|
REFLECTION_PREDEFINED_PRIMITIVE_TYPES(F) \
|
|
F(DateTime) \
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
#define REFLECTION_PREDEFINED_COMPLEX_TYPES(F, VOID_TYPE)\
|
|
F(VOID_TYPE) \
|
|
F(VoidValue) \
|
|
F(IDescriptable) \
|
|
F(DescriptableObject) \
|
|
F(DateTime) \
|
|
F(IValueEnumerator) \
|
|
F(IValueEnumerable) \
|
|
F(IValueReadonlyList) \
|
|
F(IValueArray) \
|
|
F(IValueList) \
|
|
F(IValueObservableList) \
|
|
F(IValueReadonlyDictionary) \
|
|
F(IValueDictionary) \
|
|
F(IValueInterfaceProxy) \
|
|
F(IValueFunctionProxy) \
|
|
F(IValueSubscription) \
|
|
F(IValueCallStack) \
|
|
F(IValueException) \
|
|
F(IBoxedValue) \
|
|
F(IBoxedValue::CompareResult) \
|
|
F(IValueType) \
|
|
F(IEnumType) \
|
|
F(ISerializableType) \
|
|
F(ITypeInfo) \
|
|
F(ITypeInfo::Decorator) \
|
|
F(IMemberInfo) \
|
|
F(IEventHandler) \
|
|
F(IEventInfo) \
|
|
F(IPropertyInfo) \
|
|
F(IParameterInfo) \
|
|
F(IMethodInfo) \
|
|
F(IMethodGroupInfo) \
|
|
F(TypeDescriptorFlags) \
|
|
F(ITypeDescriptor) \
|
|
|
|
DECL_TYPE_INFO(Value)
|
|
REFLECTION_PREDEFINED_PRIMITIVE_TYPES(DECL_TYPE_INFO)
|
|
REFLECTION_PREDEFINED_COMPLEX_TYPES(DECL_TYPE_INFO, void)
|
|
|
|
#endif
|
|
|
|
#undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER
|
|
|
|
/***********************************************************************
|
|
Interface Implementation Proxy (Implement)
|
|
***********************************************************************/
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4250)
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerator)
|
|
Value GetCurrent()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCurrent);
|
|
}
|
|
|
|
vint GetIndex()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetIndex);
|
|
}
|
|
|
|
bool Next()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Next);
|
|
}
|
|
END_INTERFACE_PROXY(IValueEnumerator)
|
|
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerable)
|
|
Ptr<IValueEnumerator> CreateEnumerator()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(CreateEnumerator);
|
|
}
|
|
END_INTERFACE_PROXY(IValueEnumerable)
|
|
|
|
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueReadonlyList, IValueEnumerable)
|
|
vint GetCount()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
|
|
}
|
|
|
|
Value Get(vint index)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Get, index);
|
|
}
|
|
|
|
bool Contains(const Value& value)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Contains, value);
|
|
}
|
|
|
|
vint IndexOf(const Value& value)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(IndexOf, value);
|
|
}
|
|
END_INTERFACE_PROXY(IValueReadonlyList)
|
|
|
|
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueArray, IValueReadonlyList)
|
|
void Set(vint index, const Value& value)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Set, index, value);
|
|
}
|
|
|
|
void Resize(vint size)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Resize, size);
|
|
}
|
|
END_INTERFACE_PROXY(IValueList)
|
|
|
|
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueList, IValueReadonlyList)
|
|
void Set(vint index, const Value& value)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Set, index, value);
|
|
}
|
|
|
|
vint Add(const Value& value)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Add, value);
|
|
}
|
|
|
|
vint Insert(vint index, const Value& value)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Insert, index, value);
|
|
}
|
|
|
|
bool Remove(const Value& value)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Remove, value);
|
|
}
|
|
|
|
bool RemoveAt(vint index)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(RemoveAt, index);
|
|
}
|
|
|
|
void Clear()override
|
|
{
|
|
INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
|
|
}
|
|
END_INTERFACE_PROXY(IValueList)
|
|
|
|
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueObservableList, IValueList)
|
|
END_INTERFACE_PROXY(IValueObservableList)
|
|
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueReadonlyDictionary)
|
|
Ptr<IValueReadonlyList> GetKeys()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetKeys);
|
|
}
|
|
|
|
Ptr<IValueReadonlyList> GetValues()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetValues);
|
|
}
|
|
|
|
vint GetCount()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCount);
|
|
}
|
|
|
|
Value Get(const Value& key)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Get, key);
|
|
}
|
|
END_INTERFACE_PROXY(IValueReadonlyDictionary)
|
|
|
|
BEGIN_INTERFACE_PROXY_SHAREDPTR(IValueDictionary, IValueReadonlyDictionary)
|
|
void Set(const Value& key, const Value& value)override
|
|
{
|
|
INVOKE_INTERFACE_PROXY(Set, key, value);
|
|
}
|
|
|
|
bool Remove(const Value& key)override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY(Remove, key);
|
|
}
|
|
|
|
void Clear()override
|
|
{
|
|
INVOKE_INTERFACE_PROXY_NOPARAMS(Clear);
|
|
}
|
|
END_INTERFACE_PROXY(IValueDictionary)
|
|
|
|
BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueSubscription)
|
|
bool Open()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Open);
|
|
}
|
|
|
|
bool Update()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Update);
|
|
}
|
|
|
|
bool Close()override
|
|
{
|
|
INVOKEGET_INTERFACE_PROXY_NOPARAMS(Close);
|
|
}
|
|
END_INTERFACE_PROXY(IValueSubscription)
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
extern vint ITypeDescriptor_GetTypeDescriptorCount();
|
|
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(vint index);
|
|
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const WString& name);
|
|
extern ITypeDescriptor* ITypeDescriptor_GetTypeDescriptor(const Value& value);
|
|
|
|
/***********************************************************************
|
|
LoadPredefinedTypes
|
|
***********************************************************************/
|
|
|
|
/// <summary>Register all reflectable types in <b>VlppReflection</b>.</summary>
|
|
/// <returns>Returns true if this operation succeeded.</returns>
|
|
extern bool LoadPredefinedTypes();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|