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

/// 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]. ///

///

/// 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. ///

///

/// Ptr<DescriptableObject> is recommended to replace Ptr<Object> for holding a reflectable object. /// When a class T inherits from [T:vl.reflection.Description`1], including DescriptableObject itself, /// Ptr<T> is safe to be created directly from a T* hold by another Ptr<T>. /// This is not allowed for all classes that do not inherit from [T:vl.reflection.Description`1]. ///

///
/// ///

/// 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 DescriptableObject grouping together. ///

///

/// This is called aggregation. ///

///

/// In this case, is required to do pointer casting to a C++ class. ///

///

/// To allow a C++ class to be aggregated, /// use [T:vl.reflection.AggregatableDescription`1] instead of [T:vl.reflection.Description`1], /// and call in the destructor. /// If A inherits B and they are all aggregatable, do it in both destructors. ///

///
/// /// { /// public: /// WString data; /// }; /// /// int main() /// { /// auto myClass = MakePtr(); /// myClass->data = L"Hello, world!"; /// /// Ptr obj = myClass; /// Console::WriteLine(obj.Cast()->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 or AggregatableDescription /// auto myClass2 = Ptr(dynamic_cast(obj.Obj())); /// Console::WriteLine(myClass2->data); /// } /// ]]> class DescriptableObject { template friend struct vl::ReferenceCounterOperator; template friend class Description; typedef collections::Dictionary> InternalPropertyMap; typedef bool(*DestructorProc)(DescriptableObject* obj, bool forceDisposing); private: volatile vint referenceCounter; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA size_t objectSize; description::ITypeDescriptor** typeDescriptor; #endif Ptr 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. bool IsAggregated(); // Returnd the number of aggregated base objects. vint GetAggregationSize(); // Return the object that inherit this object. 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& value); // Must be called in Workflow generated classes that inherit from aggregatable C++ classes. void InitializeAggregation(vint size); #endif /// A function that must be called in destructors of all classes inheriting from [T:vl.reflection.AggregatableDescription`1]. void FinalizeAggregation(); #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA template void SafeAggregationCast(T*& result) { auto expected = dynamic_cast(this); if (expected) { CHECK_ERROR(result == nullptr, L"vl::reflection::DescriptableObject::SafeAggregationCast()#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(result); } } } } #endif public: DescriptableObject(); virtual ~DescriptableObject(); #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA /// ///

Get the type descriptor that describe the real type of this object.

///
/// The real type. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
description::ITypeDescriptor* GetTypeDescriptor(); #endif /// /// Get an internal property of this object. /// Internal properties are totally for customization, /// they do not affect the object in anyway. /// /// Value of the internal property of this object. /// Name of the property. Ptr GetInternalProperty(const WString& name); /// /// Set an internal property of this object. /// Internal properties are totally for customization, /// they do not affect the object in anyway. /// /// Name of the property. /// Value of the internal property of this object. void SetInternalProperty(const WString& name, Ptr value); /// Try to delete this object. /// Returns true if this operation succeeded. Returns false if the object refuces to be dispose. /// 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]. bool Dispose(bool forceDisposing); #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA /// ///

Get the aggregation root object, which is the object that inherits this object by aggregation.

///
/// The aggregation root object. If this object is not aggregated, or it is the root object of others, than this function return itself. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
DescriptableObject* SafeGetAggregationRoot(); #endif /// Cast the object to another type, this is required when the object is involved in aggregation. /// The object with the expected type in all involved aggregated objects. It will crash when multiple objects are found to be qualified. /// The expected type to cast. /// ///

/// A workflow class could inherit from multiple aggregatable C++ classes. ///

///

/// 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++. ///

///

/// When VCZH_DEBUG_NO_REFLECTION is on, it performs dynamic_cast. ///

///
template T* SafeAggregationCast() { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA T* result = nullptr; SafeGetAggregationRoot()->SafeAggregationCast(result); return result; #else return dynamic_cast(this); #endif } }; /// ///

/// Inherit from this class when you want to create a reflectable class. /// It should be used like this: /// /// { /// .. /// }; /// ]]> ///

///

/// If you want YourClass to be inheritable in scripts, /// instead of using Description, /// you should use , like this: /// /// { /// ~YourClass() /// { /// FinalizeAggregation(); /// } /// }; /// ]]> ///

///

/// After you complete your type, /// use the following macros and functions to register your class into the global type table. ///

///

/// 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: ///

    ///
  • [F:vl.reflection.description.LoadPredefinedTypes]
  • ///
  • [F:vl.reflection.description.LoadParsingTypes]
  • ///
  • [F:vl.reflection.description.JsonLoadTypes]
  • ///
  • [F:vl.reflection.description.XmlLoadTypes]
  • ///
/// But if you link GacUIReflection.cpp in your project and set VCZH_DEBUG_NO_REFLECTION to off, /// all types will be automatically loaded before GuiMain is called. ///

///

/// The order does not matter, because content of types are lazily loaded. ///

///

/// Everything below should be put in vl::reflection::description namespaces. ///

    ///
  1. /// (in header files) 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. /// ///
  2. ///
  3. /// in header files) Connect type names and types: /// ///
  4. ///
  5. /// (in cpp files) Connect type names and types: /// ///
  6. ///
  7. /// (in cpp files) Register all members: ///
      ///
    • /// You will need to define a macro for commas, Whatever name is fine. /// ///
    • ///
    • /// enum: /// use BEGIN_ENUM_ITEM_MERGABLE instead of BEGIN_ENUM_ITEM if enum items are flags instead of concrete items. /// ///
    • ///
    • /// enum class: /// use BEGIN_ENUM_ITEM_MERGABLE instead of BEGIN_ENUM_ITEM if enum items are flags instead of concrete items. /// ///
    • ///
    • /// struct: /// 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. /// ///
    • ///
    • ///

      /// class: /// It doesn't necessary mean a class in C++. /// Classes in reflection and Workflow script mean reference types. ///

      ///

      /// Here are all macros that register content of classes ///

        ///
      • CLASS_MEMBER_BASE
      • ///
      • CLASS_MEMBER_FIELD
      • ///
      • CLASS_MEMBER_CONSTRUCTOR
      • ///
      • CLASS_MEMBER_EXTERNALCTOR(_TEMPLATE)?
      • ///
      • CLASS_MEMBER_METHOD(_OVERLOAD)?_RENAME
      • ///
      • CLASS_MEMBER_(STATIC_)?METHOD(_OVERLOAD)?
      • ///
      • CLASS_MEMBER_(STATIC_)?EXTERNALMETHOD(_TEMPLATE)?
      • ///
      • CLASS_MEMBER_PROPERTY(_EVENT)?(_READONLY)?(_FAST)?
      • ///
      • CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE
      • ///
      • CLASS_MEMBER_EVENT
      • ///
      ///

      ///

      /// (), NO_PARAMETER) /// /// // 05) Constructor with arguments. /// CLASS_MEMBER_CONSTRUCTOR(Ptr(int, const WString&), {L"numberParameter" _ L"stringParameter"}) /// /// // 06) Inject a global function as a constructor. /// CLASS_MEMBER_EXTERNALCTOR(Ptr(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(int, const WString&), {L"numberParameter" _ L"stringParameter"}, CreateMyClass, L"mynamespace::GetMyClass($Arguments)", L"::vl::Func<$Func>(&mynamespace::GetMyClass)") /// CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(Ptr(), NO_PARAMETER, []()->Ptr{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) /// ]]> ///

      ///

      /// If the code compiles, the class should look like this: /// /// { /// 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 XChanged; /// int GetX(); /// void SetX(int value); /// }; /// /// Ptr CreateMyClass(int numberParameter, const WString7 stringParameter); /// int GlobalFunction(MyClass* self, int parameter); /// ]]> ///

      ///
    • ///
    • ///

      /// interface: /// A C++ class can be registered as a reflectable interface if: ///

        ///
      • Directly or indirectly inherits [T:vl.reflection.IDescriptable]
      • ///
      • 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.
      • ///
      ///

      ///

      /// Suppose you have an interface like this: /// /// { /// public: /// int GetX(); /// void SetX(int value); /// }; /// ]]> ///

      ///

      /// If you want to allow a Workflow script class implement this interface, you should first add a proxy like this: /// ///

      ///

      /// And then use this code to register the interface: /// ///

      ///

      /// Everything else is the same as registering classes. /// Use BEGIN_INTERFACE_MEMBER_NOPROXY to register an interface without a proxy, /// which means a Workflow script class cannot implement this interface. ///

      ///
    • ///
    • /// Undefine the macro for comma: /// ///
    • ///
    ///
  8. ///
  9. /// (in cpp files) Create a type loader: /// ///
  10. ///
  11. /// Before using reflection on registered types, you need to register the type loader: /// AddTypeLoader(new MyTypeLoader); /// ]]> ///
  12. ///
///

///
/// Type that inherit this class. template 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 description::ITypeDescriptor* Description::associatedTypeDescriptor = 0; #endif /*********************************************************************** AggregatableDescription ***********************************************************************/ /// /// Inherit from this class when you want to create a reflectable class that can be inherited by Workflow script classes. /// /// Type that inherit this class. template class AggregatableDescription : public Description { }; /*********************************************************************** IDescriptable ***********************************************************************/ /// Base type of all reflectable interfaces. All reflectable interface types should be virtual inherited. class IDescriptable : public virtual Interface, public Description { public: ~IDescriptable(){} }; /*********************************************************************** ReferenceCounterOperator ***********************************************************************/ } template struct ReferenceCounterOperator>> { static __forceinline volatile vint* CreateCounter(T* reference) { reflection::DescriptableObject* obj=reference; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (obj->IsAggregated()) { if (auto root = obj->GetAggregationRoot()) { return &root->referenceCounter; } } #endif return &obj->referenceCounter; } static __forceinline void DeleteReference(volatile vint* counter, void* reference) { reflection::DescriptableObject* obj=(T*)reference; obj->Dispose(false); } }; namespace reflection { namespace description { /*********************************************************************** 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 ***********************************************************************/ class IBoxedValue : public virtual IDescriptable, public Description { public: enum CompareResult { Smaller, Greater, Equal, NotComparable, }; virtual Ptr Copy() = 0; virtual CompareResult ComparePrimitive(Ptr boxedValue) = 0; }; /// A type to store all values of reflectable types. /// /// To convert between Value and its real C++ type, the following functions are recommended: ///
    ///
  • [F:vl.reflection.description.BoxValue`1]
  • ///
  • [F:vl.reflection.description.UnboxValue`1]
  • ///
  • [F:vl.reflection.description.BoxParameter`1]
  • ///
  • [F:vl.reflection.description.UnboxParameter`1]
  • ///
///
class Value : public Object { public: /// How the value is stored. enum ValueType { /// The value is null. Null, /// The reference value is stored using a raw pointer. RawPtr, /// The reference value is stored using a shared pointer. SharedPtr, /// The value is stored by boxing. BoxedValue, }; protected: ValueType valueType; DescriptableObject* rawPtr; Ptr sharedPtr; Ptr boxedValue; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA ITypeDescriptor* typeDescriptor; #endif Value(DescriptableObject* value); Value(Ptr value); Value(Ptr value, ITypeDescriptor* associatedTypeDescriptor); vint Compare(const Value& a, const Value& b)const; public: /// Create a null value. Value(); Value(const Value& value); Value& operator=(const Value& value); bool operator==(const Value& value)const { return Compare(*this, value) == 0; } bool operator!=(const Value& value)const { return Compare(*this, value) != 0; } bool operator<(const Value& value)const { return Compare(*this, value)<0; } bool operator<=(const Value& value)const { return Compare(*this, value) <= 0; } bool operator>(const Value& value)const { return Compare(*this, value)>0; } bool operator>=(const Value& value)const { return Compare(*this, value) >= 0; } /// Find out how the value is stored. /// Returns How the value is stored. ValueType GetValueType()const; /// Get the stored raw pointer if GetValueType() returns RawPtr or SharedPtr. /// The stored raw pointer. Returns null if failed. DescriptableObject* GetRawPtr()const; /// Get the stored shared pointer if GetValueType() returns SharedPtr. /// The stored shared pointer. Returns null if failed. Ptr GetSharedPtr()const; /// Get the stored value if GetValueType() returns BoxedValue. /// The stored text. Returns empty if failed. Ptr GetBoxedValue()const; /// Test if this value isnull. /// Returns true if this value is null. bool IsNull()const; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA /// Get the real type of the stored object. /// The real type. Returns null if the value is null. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
ITypeDescriptor* GetTypeDescriptor()const; WString GetTypeFriendlyName()const; bool CanConvertTo(ITypeDescriptor* targetType, ValueType targetValueType)const; bool CanConvertTo(ITypeInfo* targetType)const; #endif /// Create a value from a raw pointer. /// The created value. /// The raw pointer to store. static Value From(DescriptableObject* value); /// Create a value from a shared pointer. /// The created value. /// The shared pointer to store. static Value From(Ptr value); /// Create a boxed value. /// The created value. /// The boxed value to store. /// The type of the boxed value. static Value From(Ptr value, ITypeDescriptor* type); #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA static IMethodInfo* SelectMethod(IMethodGroupInfo* methodGroup, collections::Array& arguments); /// Call the default constructor of the specified type to create a value. /// The created value. /// The type to create the value. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
static Value Create(ITypeDescriptor* type); /// Call the constructor of the specified type to create a value. /// The created value. /// The type to create the value. /// Arguments for the constructor. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(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>(myClass); /// Console::WriteLine(ptrMyClass1->data); /// /// Ptr ptrMyClass2; /// UnboxParameter(myClass, ptrMyClass2); /// Console::WriteLine(ptrMyClass2->data); /// } /// DestroyGlobalTypeManager(); /// } /// ]]> static Value Create(ITypeDescriptor* type, collections::Array& arguments); /// Call the default constructor of the specified type to create a value. /// The created value. /// The registered full name for the type to create the value. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
static Value Create(const WString& typeName); /// Call the constructor of the specified type to create a value. /// The created value. /// The registered full name for the type to create the value. /// Arguments for the constructor. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(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>(myClass); /// Console::WriteLine(ptrMyClass1->data); /// /// Ptr ptrMyClass2; /// UnboxParameter(myClass, ptrMyClass2); /// Console::WriteLine(ptrMyClass2->data); /// } /// DestroyGlobalTypeManager(); /// } /// ]]> static Value Create(const WString& typeName, collections::Array& arguments); /// Call a static method of the specified type. /// The return value from that method. /// The registered full name for the type. /// The registered name for the method. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
static Value InvokeStatic(const WString& typeName, const WString& name); /// Call a static method of the specified type. /// The return value from that method. /// The registered full name for the type. /// The registered name for the method. /// Arguments for the method. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(); /// } /// ]]> static Value InvokeStatic(const WString& typeName, const WString& name, collections::Array& arguments); /// Call the getter function for a property. /// The value of the property. /// The registered name for the property. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(), 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(L"Hello, world!")); /// myClass.SetProperty(L"Prop", BoxValue(L"Hello, Gaclib!")); /// /// Console::WriteLine(UnboxValue(myClass.GetProperty(L"field"))); /// Console::WriteLine(UnboxValue(myClass.GetProperty(L"Prop"))); /// } /// DestroyGlobalTypeManager(); /// } /// ]]> Value GetProperty(const WString& name)const; /// Call the setter function for a property. /// The registered name for the property. /// The value to set the property. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(), 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(L"Hello, world!")); /// myClass.SetProperty(L"Prop", BoxValue(L"Hello, Gaclib!")); /// /// Console::WriteLine(UnboxValue(myClass.GetProperty(L"field"))); /// Console::WriteLine(UnboxValue(myClass.GetProperty(L"Prop"))); /// } /// DestroyGlobalTypeManager(); /// } /// ]]> void SetProperty(const WString& name, const Value& newValue); /// Call a non-static method. /// The return value from that method. /// The registered name for the method. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
Value Invoke(const WString& name)const; /// Call a non-static method. /// The return value from that method. /// The registered name for the method. /// Arguments for the method. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// 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(), 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(); /// } /// ]]> Value Invoke(const WString& name, collections::Array& arguments)const; /// Attach a callback function for the event. /// The event handler for this attachment. You need to keep it to detach the callback function. /// The registered name for the event. /// The callback function. /// ///

Only available when VCZH_DEBUG_NO_REFLECTION is off.

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

Only available when VCZH_DEBUG_NO_REFLECTION is off.

///
/// /// { /// private: /// WString prop; /// public: /// Event PropChanged; /// /// WString GetProp() /// { /// return prop; /// } /// /// void SetProp(const WString& value) /// { /// if (prop != value) /// { /// auto old = prop; /// prop = value; /// PropChanged(old, prop); /// } /// } /// }; /// } /// /// #define MY_TYPELIST(F)\ /// F(mynamespace::MyClass)\ /// /// // it is recommended to put the content below in a separated header file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// MY_TYPELIST(DECL_TYPE_INFO) /// } /// } /// } /// /// // it is recommended to put the content below in a separated cpp file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// using namespace mynamespace; /// /// #define _ , /// /// MY_TYPELIST(IMPL_CPP_TYPE_INFO) /// /// BEGIN_CLASS_MEMBER(MyClass) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(), NO_PARAMETER) /// CLASS_MEMBER_EVENT(PropChanged) /// CLASS_MEMBER_PROPERTY_EVENT_FAST(Prop, PropChanged) /// END_CLASS_MEMBER(MyClass) /// /// #undef _ /// } /// } /// } /// /// class MyTypeLoader : public Object, public ITypeLoader /// { /// public: /// void Load(ITypeManager* manager) /// { /// MY_TYPELIST(ADD_TYPE_INFO) /// } /// /// void Unload(ITypeManager* manager) /// { /// } /// }; /// /// // main function /// /// int main() /// { /// LoadPredefinedTypes(); /// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader); /// GetGlobalTypeManager()->Load(); /// { /// auto td = GetTypeDescriptor(L"mynamespace::MyClass"); /// auto myClass = Value::Create(td); /// myClass.SetProperty(L"Prop", BoxValue(L"Zero")); /// /// using CallbackType = Func; /// CallbackType callbackFunction = [](const WString& oldProp, const WString& newProp) /// { /// Console::WriteLine(L"myClass.Prop changed: " + oldProp + L" -> " + newProp); /// }; /// auto handler = myClass.AttachEvent(L"PropChanged", BoxParameter(callbackFunction)); /// /// myClass.SetProperty(L"Prop", BoxValue(L"One")); /// myClass.SetProperty(L"Prop", BoxValue(L"Two")); /// myClass.DetachEvent(L"PropChanged", handler); /// myClass.SetProperty(L"Prop", BoxValue(L"Three")); /// } /// DestroyGlobalTypeManager(); /// } /// ]]> bool DetachEvent(const WString& name, Ptr handler)const; #endif /// Dispose the object if GetValueType() returns RawPtr. /// /// 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. /// /// /// { /// public: /// SharedClass() /// { /// Console::WriteLine(L"SharedClass::SharedClass()"); /// } /// /// ~SharedClass() /// { /// Console::WriteLine(L"SharedClass::~SharedClass()"); /// } /// }; /// /// class RawClass : public Object, public Description /// { /// 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(), 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(); /// } /// ]]> 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 struct TypedValueSerializerProvider; } namespace description { /*********************************************************************** ValueType ***********************************************************************/ class IValueType : public virtual IDescriptable, public Description { public: template class TypedBox : public IBoxedValue { private: template static CompareResult ComparePrimitiveInternal(const U& a, const U& b, std::enable_if_t::Compare)) >= 0, vint>) { return TypedValueSerializerProvider::Compare(a, b); } template static CompareResult ComparePrimitiveInternal(const U& a, const U& b, double) { #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdynamic-class-memaccess" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif auto result = memcmp(&a, &b, sizeof(U)); #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif if (result < 0) return IBoxedValue::Smaller; if (result > 0) return IBoxedValue::Greater; return IBoxedValue::Equal; } public: T value; TypedBox() :value{} { } TypedBox(const T& _value) :value(_value) { } Ptr Copy()override { return new TypedBox(value); } CompareResult ComparePrimitive(Ptr boxedValue)override { if (auto typedBox = boxedValue.Cast>()) { return ComparePrimitiveInternal(value, typedBox->value, (vint)0); } else { return IBoxedValue::NotComparable; } } }; virtual Value CreateDefault() = 0; virtual IBoxedValue::CompareResult Compare(const Value& a, const Value& b) = 0; }; class IEnumType : public virtual IDescriptable, public Description { 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 { 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 { 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 { public: virtual ITypeDescriptor* GetOwnerTypeDescriptor()=0; virtual const WString& GetName()=0; }; /*********************************************************************** ITypeDescriptor (event) ***********************************************************************/ class IEventHandler : public virtual IDescriptable, public Description { public: virtual bool IsAttached()=0; }; class IEventInfo : public virtual IMemberInfo, public Description { public: class ICpp : public virtual IDescriptable, public Description { 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 Attach(const Value& thisObject, Ptr handler)=0; virtual bool Detach(const Value& thisObject, Ptr handler)=0; virtual void Invoke(const Value& thisObject, Ptr arguments)=0; }; /*********************************************************************** ITypeDescriptor (property) ***********************************************************************/ class IPropertyInfo : public virtual IMemberInfo, public Description { public: class ICpp : public virtual IDescriptable, public Description { 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 { public: virtual ITypeInfo* GetType()=0; virtual IMethodInfo* GetOwnerMethod()=0; }; class IMethodInfo : public virtual IMemberInfo, public Description { public: class ICpp : public virtual IDescriptable, public Description { 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: ($Arguments) External method: ($This, $Arguments) Renamed method: $This->($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& arguments)=0; virtual Value Invoke(const Value& thisObject, collections::Array& arguments)=0; virtual Value CreateFunctionProxy(const Value& thisObject) = 0; }; class IMethodGroupInfo : public virtual IMemberInfo, public Description { 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); } /// Metadata class for reflectable types. class ITypeDescriptor : public virtual IDescriptable, public Description { public: class ICpp : public virtual IDescriptable, public Description { 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; /// Delay loading for registering reflectable types. class ITypeLoader : public virtual Interface { public: /// Called when it is time to register types. /// The type manager. virtual void Load(ITypeManager* manager)=0; /// Called when it is time to unregister types. /// The type manager. /// /// 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 . /// virtual void Unload(ITypeManager* manager)=0; }; /// A type manager to access all reflectable types. class ITypeManager : public virtual Interface { public: /// Get the number of all registered types. /// The number of all registered types. virtual vint GetTypeDescriptorCount()=0; /// Get one registered type. /// A registered type specified by the index. /// The index for retriving the registered type. /// /// 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. /// virtual ITypeDescriptor* GetTypeDescriptor(vint index)=0; virtual ITypeDescriptor* GetTypeDescriptor(const WString& name)=0; virtual bool SetTypeDescriptor(const WString& name, Ptr typeDescriptor)=0; /// Delay register some types. /// Returns true if this operation succeeded. /// A type loader for delay registering. /// /// You can still call this function after is called. /// In this case, there is no delay registering, all types in this loader will be registered immediately. /// virtual bool AddTypeLoader(Ptr typeLoader)=0; virtual bool RemoveTypeLoader(Ptr typeLoader)=0; /// Load all added type loaders. /// Returns true if this operation succeeded. virtual bool Load()=0; virtual bool Unload()=0; virtual bool Reload()=0; virtual bool IsLoaded()=0; virtual ITypeDescriptor* GetRootType()=0; virtual vint GetTypeVersion()=0; }; /// Get the type manager. /// Returns the type manager. extern ITypeManager* GetGlobalTypeManager(); /// Unload all types and free the type manager. /// Returns true if this operation succeeded. /// /// After calling this function, you can no longer register new types, /// and calling will always get null. /// extern bool DestroyGlobalTypeManager(); /// Unload all types and reset the type manager. /// Returns true if this operation succeeded. /// ///

/// This function is similar to , /// but calling this function allows types to be registsred again. ///

///

/// 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. ///

///
extern bool ResetGlobalTypeManager(); /// Get a registered type given the registered name. /// Returns the metadata class for this registered type. /// /// 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. /// /// Returning null means the type registration is declared but the type manager has not started. /// 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 LoadMetaonlyTypes(stream::IStream& inputStream, const collections::Dictionary>& 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 { /// Base type of observable container which triggers callbacks whenever items are changed. /// Type of elements. /// Type of the key type of elements. It is recommended to use the default value. /// ///

Methods are the same to , except that operator[] is readonly.

///

/// When an item is being inserted to the list, /// QueryInsert will be called to determine if this item can be inserted, /// BeforeInsert will be called before inserting, /// AfterInsert will be called after inserting. ///

///

/// When an item is being removed from the list, /// QueryRemove will be called to determine if this item can be removed, /// BeforeRemove will be called before removing, /// AfterRemove will be called after removing. ///

///

/// When an item is being replaced, it is considered as removing the original item and inserting the new item. ///

///

/// After any changing happens, NotifyUpdateInternal is called. /// Arguments is exactly the same as . ///

///
template::Type> class ObservableListBase : public collections::EnumerableBase { protected: collections::List 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* CreateEnumerator()const { return items.CreateEnumerator(); } /// Trigger NotifyUpdateInternal manually. /// Returns true if arguments are not out of range. /// The index of the first item that are changed. /// The number of items that are changed, the default value is 1. /// ///

/// 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. ///

///

/// If subscribers need to know about such change, calling this function is an easy way to do it. ///

///
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 && indexAn observable container that maintain an implementation of . /// Type of elements. /// Type of the key type of elements. It is recommended to use the default value. template class ObservableList : public ObservableListBase { protected: void NotifyUpdateInternal(vint start, vint count, vint newCount) override; public: }; namespace randomaccess_internal { template struct RandomAccessable> { static const bool CanRead = true; static const bool CanResize = false; }; template struct RandomAccessable> { static const bool CanRead = true; static const bool CanResize = false; }; } } } #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 namespace vl { namespace reflection { namespace description { struct VoidValue {}; /*********************************************************************** Collections ***********************************************************************/ /// The reflectable version of . class IValueEnumerator : public virtual IDescriptable, public Description { public: /// Get the reference to the current value in the enumerator. /// The current value. /// needs to be called to make the first value available. virtual Value GetCurrent() = 0; /// Get the position of the current value in the enumerator. /// The position of the current value. virtual vint GetIndex() = 0; /// Prepare for the next value. /// Returns false if there is no more value. virtual bool Next() = 0; }; /// The reflectable version of . /// will create a storing a shared pointer to an instance of this interface from an enumerable. /// /// { /// public: /// MyClass(vint _data = 0) /// :data(_data) /// { /// } /// /// vint data; /// }; /// } /// /// #define MY_TYPELIST(F)\ /// F(mynamespace::MyClass)\ /// /// // it is recommended to put the content below in a separated header file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// MY_TYPELIST(DECL_TYPE_INFO) /// } /// } /// } /// /// // it is recommended to put the content below in a separated cpp file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// using namespace mynamespace; /// /// #define _ , /// /// MY_TYPELIST(IMPL_CPP_TYPE_INFO) /// /// BEGIN_CLASS_MEMBER(MyClass) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(vint), { L"data" }) /// CLASS_MEMBER_FIELD(data) /// END_CLASS_MEMBER(MyClass) /// /// #undef _ /// } /// } /// } /// /// class MyTypeLoader : public Object, public ITypeLoader /// { /// public: /// void Load(ITypeManager* manager) /// { /// MY_TYPELIST(ADD_TYPE_INFO) /// } /// /// void Unload(ITypeManager* manager) /// { /// } /// }; /// /// // main function /// /// int main() /// { /// LoadPredefinedTypes(); /// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader); /// GetGlobalTypeManager()->Load(); /// { /// LazyList> cs = Range(1, 10) /// .Select([](vint i) /// { /// return MakePtr(i); /// }); /// /// Value boxed = BoxParameter(cs); /// { /// auto enumerable = UnboxValue>(boxed); /// auto enumerator = enumerable->CreateEnumerator(); /// while (enumerator->Next()) /// { /// Console::Write(itow(UnboxValue>(enumerator->GetCurrent())->data) + L" "); /// } /// Console::WriteLine(L""); /// } /// { /// auto enumerator = boxed.Invoke(L"CreateEnumerator"); /// while (UnboxValue(enumerator.Invoke(L"Next"))) /// { /// Console::Write(itow(UnboxValue(enumerator.GetProperty(L"Current").GetProperty(L"data"))) + L" "); /// } /// Console::WriteLine(L""); /// } /// } /// DestroyGlobalTypeManager(); /// } /// ]]> class IValueEnumerable : public virtual IDescriptable, public Description { public: /// /// Create an enumerator. should be called before reading the first value. /// /// The enumerator. virtual Ptr CreateEnumerator() = 0; /// Get the underlying collection object, which is boxed to be this interface. /// The underlying collection object, could be nullptr. virtual const Object* GetCollectionObject() { return nullptr; } /// Create an enumerable from another lazy list. /// The created enumerable. /// The lazy list to wrap. static Ptr Create(collections::LazyList values); }; /// /// The reflectable version of readonly /// , /// or /// /// /// /// class IValueReadonlyList : public virtual IValueEnumerable, public Description { public: /// Get the number of elements in the container. /// The number of elements. virtual vint GetCount() = 0; /// Get the reference to the specified element. /// The reference to the specified element. It will crash when the index is out of range. /// The index of the element. virtual Value Get(vint index) = 0; /// Test does the list contain a value or not. /// Returns true if the list contains the specified value. /// The value to test. virtual bool Contains(const Value& value) = 0; /// Get the position of a value in this list. /// Returns the position of first element that equals to the specified value. Returns -1 if failed to find. /// The value to find. virtual vint IndexOf(const Value& value) = 0; }; /// /// The reflectable version of writable /// /// /// will create a storing a shared pointer to an instance of this interface from a container. class IValueArray : public virtual IValueReadonlyList, public Description { public: /// Replace an element in the specified position. /// Returns true if this operation succeeded. It will crash when the index is out of range /// The position of the element to replace. /// The new value to replace. virtual void Set(vint index, const Value& value) = 0; /// Append a value at the end of the list. /// The index of the added item. /// The value to add. virtual void Resize(vint size) = 0; /// Create an empty array. /// The created list. static Ptr Create(); /// Create an array with elements copied from another readonly list. /// The created list. /// Elements to copy. static Ptr Create(Ptr values); /// Create an array with elements copied from another lazy list. /// The created list. /// Elements to copy. static Ptr Create(collections::LazyList values); }; /// /// The reflectable version of writable /// or /// or /// /// /// will create a storing a shared pointer to an instance of this interface from a container. /// /// { /// public: /// MyClass(vint _data = 0) /// :data(_data) /// { /// } /// /// vint data; /// }; /// } /// /// #define MY_TYPELIST(F)\ /// F(mynamespace::MyClass)\ /// /// // it is recommended to put the content below in a separated header file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// MY_TYPELIST(DECL_TYPE_INFO) /// } /// } /// } /// /// // it is recommended to put the content below in a separated cpp file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// using namespace mynamespace; /// /// #define _ , /// /// MY_TYPELIST(IMPL_CPP_TYPE_INFO) /// /// BEGIN_CLASS_MEMBER(MyClass) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(vint), { L"data" }) /// CLASS_MEMBER_FIELD(data) /// END_CLASS_MEMBER(MyClass) /// /// #undef _ /// } /// } /// } /// /// class MyTypeLoader : public Object, public ITypeLoader /// { /// public: /// void Load(ITypeManager* manager) /// { /// MY_TYPELIST(ADD_TYPE_INFO) /// } /// /// void Unload(ITypeManager* manager) /// { /// } /// }; /// /// // main function /// /// int main() /// { /// LoadPredefinedTypes(); /// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader); /// GetGlobalTypeManager()->Load(); /// { /// List> cs; /// CopyFrom(cs, Range(1, 10) /// .Select([](vint i) /// { /// return MakePtr(i); /// }) /// ); /// /// Value boxed = BoxParameter(cs); /// { /// auto list = UnboxValue>(boxed); /// for (vint i = 0; i < list->GetCount(); i++) /// { /// Console::Write(itow(UnboxValue>(list->Get(i))->data) + L" "); /// } /// Console::WriteLine(L""); /// } /// /// for (vint i = 1; i <= 5; i++) /// { /// cs.RemoveAt(i); /// } /// /// { /// for (vint i = 0; i < UnboxValue(boxed.GetProperty(L"Count")); i++) /// { /// Console::Write(itow(UnboxValue(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" "); /// } /// Console::WriteLine(L""); /// } /// } /// DestroyGlobalTypeManager(); /// } /// ]]> class IValueList : public virtual IValueReadonlyList, public Description { public: /// Replace an element in the specified position. /// Returns true if this operation succeeded. It will crash when the index is out of range /// The position of the element to replace. /// The new value to replace. virtual void Set(vint index, const Value& value) = 0; /// Append a value at the end of the list. /// The index of the added item. /// The value to add. virtual vint Add(const Value& value) = 0; /// Insert a value at the specified position. /// The index of the added item. It will crash if the index is out of range /// The position to insert the value. /// The value to add. virtual vint Insert(vint index, const Value& value) = 0; /// Remove an element from the list. If multiple elements equal to the specified value, only the first one will be removed. /// Returns true if the element is removed. /// The item to remove. virtual bool Remove(const Value& value) = 0; /// Remove an element at a specified position. /// Returns true if the element is removed. It will crash when the index is out of range. /// The index of the element to remove. virtual bool RemoveAt(vint index) = 0; /// Remove all elements. virtual void Clear() = 0; /// Create an empty list. /// The created list. static Ptr Create(); /// Create a list with elements copied from another readonly list. /// The created list. /// Elements to copy. static Ptr Create(Ptr values); /// Create a list with elements copied from another lazy list. /// The created list. /// Elements to copy. static Ptr Create(collections::LazyList values); }; /// /// The reflectable version of list container which triggers an event whenever items are changed. /// /// /// { /// public: /// MyClass(vint _data = 0) /// :data(_data) /// { /// } /// /// vint data; /// }; /// } /// /// #define MY_TYPELIST(F)\ /// F(mynamespace::MyClass)\ /// /// // it is recommended to put the content below in a separated header file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// MY_TYPELIST(DECL_TYPE_INFO) /// } /// } /// } /// /// // it is recommended to put the content below in a separated cpp file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// using namespace mynamespace; /// /// #define _ , /// /// MY_TYPELIST(IMPL_CPP_TYPE_INFO) /// /// BEGIN_CLASS_MEMBER(MyClass) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(vint), { L"data" }) /// CLASS_MEMBER_FIELD(data) /// END_CLASS_MEMBER(MyClass) /// /// #undef _ /// } /// } /// } /// /// class MyTypeLoader : public Object, public ITypeLoader /// { /// public: /// void Load(ITypeManager* manager) /// { /// MY_TYPELIST(ADD_TYPE_INFO) /// } /// /// void Unload(ITypeManager* manager) /// { /// } /// }; /// /// // main function /// /// int main() /// { /// LoadPredefinedTypes(); /// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader); /// GetGlobalTypeManager()->Load(); /// { /// ObservableList> cs; /// CopyFrom(cs, Range(1, 10) /// .Select([](vint i) /// { /// return MakePtr(i); /// }) /// ); /// /// Value boxed = BoxParameter(cs); /// auto list = UnboxValue>(boxed); /// { /// for (vint i = 0; i < list->GetCount(); i++) /// { /// Console::Write(itow(UnboxValue>(list->Get(i))->data) + L" "); /// } /// Console::WriteLine(L""); /// } /// /// { /// using CallbackType = Func; /// 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(boxed.GetProperty(L"Count")); i++) /// { /// Console::Write(itow(UnboxValue(boxed.Invoke(L"Get", (Value_xs(), i)).GetProperty(L"data"))) + L" "); /// } /// Console::WriteLine(L""); /// } /// } /// DestroyGlobalTypeManager(); /// } /// ]]> class IValueObservableList : public virtual IValueList, public Description { typedef void ItemChangedProc(vint index, vint oldCount, vint newCount); public: /// ///

Event that is triggered whenever items are changed.

///

The first argument is the index of the first item that is changed.

///

The second argument is the number of original items that are replaced by new items.

///

The third argument is the number of new items that replace original items.

///
/// ///

If an item is changed, oldCount and newCount are both 1.

///

If several items are removed from the list, newCount is 0.

///

If several items are inserted to the list, oldCount is 0.

///

This event is triggered when the updating is done, original items are not possible to access at the moment.

///
Event ItemChanged; /// Create an empty list. /// The created list. static Ptr Create(); /// Create a list with elements copied from another readonly list. /// The created list. /// Elements to copy. static Ptr Create(Ptr values); /// Create a list with elements copied from another lazy list. /// The created list. /// Elements to copy. static Ptr Create(collections::LazyList values); }; /// /// The reflectable version of readonly . /// class IValueReadonlyDictionary : public virtual IDescriptable, public Description { public: /// Get all keys. /// All keys. virtual Ptr GetKeys() = 0; /// Get all values. /// All values. virtual Ptr GetValues() = 0; /// Get the number of keys. /// The number of keys. It is also the number of values. virtual vint GetCount() = 0; /// Get the value associated to a specified key. /// The reference to the value. It will crash if the key does not exist. /// The key to find. virtual Value Get(const Value& key) = 0; /// Get the underlying collection object, which is boxed to be this interface. /// The underlying collection object, could be nullptr. virtual const Object* GetCollectionObject() { return nullptr; } }; /// /// The reflectable version of writable . /// /// will create a storing a shared pointer to an instance of this interface from a dictionary. /// /// { /// public: /// MyClass(vint _data = 0) /// :data(_data) /// { /// } /// /// vint data; /// }; /// } /// /// #define MY_TYPELIST(F)\ /// F(mynamespace::MyClass)\ /// /// // it is recommended to put the content below in a separated header file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// MY_TYPELIST(DECL_TYPE_INFO) /// } /// } /// } /// /// // it is recommended to put the content below in a separated cpp file /// /// namespace vl /// { /// namespace reflection /// { /// namespace description /// { /// using namespace mynamespace; /// /// #define _ , /// /// MY_TYPELIST(IMPL_CPP_TYPE_INFO) /// /// BEGIN_CLASS_MEMBER(MyClass) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(), NO_PARAMETER) /// CLASS_MEMBER_CONSTRUCTOR(Ptr(vint), { L"data" }) /// CLASS_MEMBER_FIELD(data) /// END_CLASS_MEMBER(MyClass) /// /// #undef _ /// } /// } /// } /// /// class MyTypeLoader : public Object, public ITypeLoader /// { /// public: /// void Load(ITypeManager* manager) /// { /// MY_TYPELIST(ADD_TYPE_INFO) /// } /// /// void Unload(ITypeManager* manager) /// { /// } /// }; /// /// // main function /// /// int main() /// { /// LoadPredefinedTypes(); /// GetGlobalTypeManager()->AddTypeLoader(new MyTypeLoader); /// GetGlobalTypeManager()->Load(); /// { /// Dictionary> cs; /// CopyFrom(cs, Range(1, 10) /// .Select([](vint i) -> Pair> /// { /// return { i, MakePtr(i * i) }; /// }) /// ); /// /// Value boxed = BoxParameter(cs); /// { /// auto dictionary = UnboxValue>(boxed); /// for (vint i = 0; i < dictionary->GetCount(); i++) /// { /// Value key = dictionary->GetKeys()->Get(i); /// Console::Write(itow(UnboxValue>(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(boxed.GetProperty(L"Count")); i++) /// { /// Value key = boxed.GetProperty(L"Keys").Invoke(L"Get", (Value_xs(), i)); /// Console::Write(itow(UnboxValue(boxed.Invoke(L"Get", (Value_xs(), key)).GetProperty(L"data"))) + L" "); /// } /// Console::WriteLine(L""); /// } /// } /// DestroyGlobalTypeManager(); /// } /// ]]> class IValueDictionary : public virtual IValueReadonlyDictionary, public Description { public: /// Replace the value associated to a specified key. /// Returns true if the value is replaced. /// The key to find. If the key does not exist, it will be added to the dictionary. /// The associated value to replace. virtual void Set(const Value& key, const Value& value) = 0; /// Remove a key with the associated value. /// Returns true if the key and the value is removed. /// The key to find. virtual bool Remove(const Value& key) = 0; /// Remove all elements. virtual void Clear() = 0; /// Create an empty dictionary. /// The created dictionary. static Ptr Create(); /// Create a dictionary with elements copied from another readonly dictionary. /// The created dictionary. /// Elements to copy. static Ptr Create(Ptr values); /// Create a dictionary with elements copied from another lazy list. /// The created dictionary. /// Elements to copy. static Ptr Create(collections::LazyList> values); }; /*********************************************************************** Interface Implementation Proxy ***********************************************************************/ class IValueInterfaceProxy : public virtual IDescriptable, public Description { public: virtual Value Invoke(IMethodInfo* methodInfo, Ptr arguments) = 0; }; /// A reflectable version of . /// will create a storing a shared pointer to an instance of this interface from a function. class IValueFunctionProxy : public virtual IDescriptable, public Description { public: /// Call the function. /// Return value from the function. /// Arguments to call the function. virtual Value Invoke(Ptr arguments) = 0; }; /// A reflectable subscription, usually created by the bind expression in Workflow script. class IValueSubscription : public virtual IDescriptable, public Description { typedef void ValueChangedProc(const Value& newValue); public: /// Event that triggered when the binding source is changed. /// The first argument is the new value of the binding source. Event ValueChanged; /// Start the subscription. /// Returns true if this operation succeeded. virtual bool Open() = 0; /// Manually trigger the event. /// Returns true if this operation succeeded. virtual bool Update() = 0; /// Stop the subscription. /// Returns true if this operation succeeded. virtual bool Close() = 0; }; /*********************************************************************** Interface Implementation Proxy (Implement) ***********************************************************************/ class ValueInterfaceRoot : public virtual IDescriptable { protected: Ptr proxy; void SetProxy(Ptr value) { proxy = value; } public: Ptr GetProxy() { return proxy; } }; template class ValueInterfaceProxy { }; #pragma warning(push) #pragma warning(disable:4250) template class ValueInterfaceImpl : public virtual ValueInterfaceRoot, public virtual TInterface, public ValueInterfaceProxy... { public: ~ValueInterfaceImpl() { FinalizeAggregation(); } }; #pragma warning(pop) /*********************************************************************** Runtime Exception ***********************************************************************/ class IValueCallStack : public virtual IDescriptable, public Description { public: virtual Ptr GetLocalVariables() = 0; virtual Ptr GetLocalArguments() = 0; virtual Ptr GetCapturedVariables() = 0; virtual Ptr 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 { 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 GetCallStack() = 0; static Ptr 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 struct TypeInfoRetriver; /// /// A reference holder to an unboxed object. /// /// The type of the unboxed object. template struct Unboxed { private: T* object; bool owned; public: Unboxed(T* _object, bool _owned) : object(_object), owned(_owned) {} Unboxed(Unboxed&& unboxed) : object(unboxed.object), owned(unboxed.owned) { unboxed.object = nullptr; } ~Unboxed() { if (object && owned) { delete object; } } Unboxed() = delete; Unboxed(const Unboxed&&) = delete; Unboxed& operator=(const Unboxed&) = delete; Unboxed& operator=(Unboxed&&) = delete; /// /// Get the reference of the unboxed object. /// It is recommended only to use this reference when the is still alive. /// /// The unboxed object. T& Ref() const { CHECK_ERROR(object, L"vl::reflection::description::Unboxed::Ref()#The object has been moved away."); return *object; } /// /// Test if the unboxed object is owned. /// /// bool IsOwned() const { return owned; } }; template Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor = nullptr); template T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor = nullptr, const WString& valueName = WString::Unmanaged(L"value")); template Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor = nullptr); template Unboxed 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{ static const TypeInfoContent content; }; #define IMPL_VL_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo::content = { L ## #TYPENAME, nullptr, TypeInfoContent::VlppType }; #define IMPL_CPP_TYPE_INFO(TYPENAME) const TypeInfoContent TypeInfo::content = { L ## #TYPENAME, nullptr, TypeInfoContent::CppType }; #define IMPL_TYPE_INFO_RENAME(TYPENAME, EXPECTEDNAME) const TypeInfoContent TypeInfo::content = { L ## #EXPECTEDNAME, L ## #TYPENAME, TypeInfoContent::Renamed }; struct TypeInfoContent { enum TypeInfoCppName { VlppType, // vl:: CppType, // Renamed, // CppFullTypeName }; const wchar_t* typeName; const wchar_t* cppFullTypeName; TypeInfoCppName cppName; }; template struct TypeInfo; /// Get a registered type given a C++ type. /// Returns the metadata class for this registered type. /// The C++ type to get the registered type. /// /// 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 about how to register a type. /// template ITypeDescriptor* GetTypeDescriptor() { static vint typeVersion = -1; static ITypeDescriptor* cached = nullptr; if (auto tm = GetGlobalTypeManager()) { auto currentVersion = tm->GetTypeVersion(); if (typeVersion != currentVersion) { cached = GetTypeDescriptor(TypeInfo::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 elementType; public: DecoratedTypeInfo(Ptr _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 _elementType); ~RawPtrTypeInfo(); Decorator GetDecorator()override; WString GetTypeFriendlyName()override; }; class SharedPtrTypeInfo : public DecoratedTypeInfo { public: SharedPtrTypeInfo(Ptr _elementType); ~SharedPtrTypeInfo(); Decorator GetDecorator()override; WString GetTypeFriendlyName()override; }; class NullableTypeInfo : public DecoratedTypeInfo { public: NullableTypeInfo(Ptr _elementType); ~NullableTypeInfo(); Decorator GetDecorator()override; WString GetTypeFriendlyName()override; }; class GenericTypeInfo : public DecoratedTypeInfo { protected: collections::List> genericArguments; public: GenericTypeInfo(Ptr _elementType); ~GenericTypeInfo(); Decorator GetDecorator()override; vint GetGenericArgumentCount()override; ITypeInfo* GetGenericArgument(vint index)override; WString GetTypeFriendlyName()override; void AddGenericArgument(Ptr 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 valueType; Ptr enumType; Ptr 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 class TypedValueTypeDescriptorBase : public ValueTypeDescriptorBase { public: TypedValueTypeDescriptorBase() :ValueTypeDescriptorBase(TDFlags, &TypeInfo::content) { } }; /*********************************************************************** ParameterInfoImpl ***********************************************************************/ class ParameterInfoImpl : public Object, public IParameterInfo { protected: IMethodInfo* ownerMethod; WString name; Ptr type; public: ParameterInfoImpl(IMethodInfo* _ownerMethod, const WString& _name, Ptr _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> parameters; Ptr returnInfo; bool isStatic; virtual Value InvokeInternal(const Value& thisObject, collections::Array& arguments)=0; virtual Value CreateFunctionProxyInternal(const Value& thisObject) = 0; public: MethodInfoImpl(IMethodGroupInfo* _ownerMethodGroup, Ptr _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& arguments)override; Value Invoke(const Value& thisObject, collections::Array& arguments)override; Value CreateFunctionProxy(const Value& thisObject)override; bool AddParameter(Ptr parameter); bool SetOwnerMethodgroup(IMethodGroupInfo* _ownerMethodGroup); }; /*********************************************************************** MethodGroupInfoImpl ***********************************************************************/ class MethodGroupInfoImpl : public Object, public IMethodGroupInfo { protected: ITypeDescriptor* ownerTypeDescriptor; WString name; collections::List> 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 _method); }; /*********************************************************************** EventInfoImpl ***********************************************************************/ class EventInfoImpl : public Object, public IEventInfo { friend class PropertyInfoImpl; protected: ITypeDescriptor* ownerTypeDescriptor; collections::List observingProperties; WString name; Ptr handlerType; virtual Ptr AttachInternal(DescriptableObject* thisObject, Ptr handler)=0; virtual bool DetachInternal(DescriptableObject* thisObject, Ptr handler)=0; virtual void InvokeInternal(DescriptableObject* thisObject, Ptr arguments)=0; virtual Ptr 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 Attach(const Value& thisObject, Ptr handler)override; bool Detach(const Value& thisObject, Ptr handler)override; void Invoke(const Value& thisObject, Ptr arguments)override; }; /*********************************************************************** TypeDescriptorImpl ***********************************************************************/ class PropertyInfoImpl : public Object, public IPropertyInfo { protected: ITypeDescriptor* ownerTypeDescriptor; WString name; Ptr 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 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 _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 baseTypeDescriptors; collections::Dictionary> properties; collections::Dictionary> events; collections::Dictionary> methodGroups; Ptr constructorGroup; protected: MethodGroupInfoImpl* PrepareMethodGroup(const WString& name); MethodGroupInfoImpl* PrepareConstructorGroup(); IPropertyInfo* AddProperty(Ptr value); IEventInfo* AddEvent(Ptr value); IMethodInfo* AddMethod(const WString& name, Ptr value); IMethodInfo* AddConstructor(Ptr 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 class CustomFieldInfoImpl : public FieldInfoImpl { protected: TField TClass::* fieldRef; Value GetValueInternal(const Value& thisObject)override { TClass* object = UnboxValue(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) { TClass* object = UnboxValue(thisObject); if (object) { auto result = UnboxParameter(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::CreateTypeInfo()) , fieldRef(_fieldRef) { } IPropertyInfo::ICpp* GetCpp()override { return nullptr; } bool IsWritable()override { return std::is_copy_assignable_v; } }; #endif /*********************************************************************** PrimitiveTypeDescriptor ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION template class SerializableValueType : public Object, public virtual IValueType { public: Value CreateDefault()override { return BoxValue(TypedValueSerializerProvider::GetDefaultValue()); } IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override { auto va = UnboxValue(a); auto vb = UnboxValue(b); return TypedValueSerializerProvider::Compare(va, vb); } }; template class SerializableType : public Object, public virtual ISerializableType { public: bool Serialize(const Value& input, WString& output)override { return TypedValueSerializerProvider::Serialize(UnboxValue(input), output); } bool Deserialize(const WString& input, Value& output)override { T value; if (!TypedValueSerializerProvider::Deserialize(input, value)) { return false; } output = BoxValue(value); return true; } }; #endif #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA template class PrimitiveTypeDescriptor : public TypedValueTypeDescriptorBase { protected: void LoadInternal()override { this->valueType = new SerializableValueType(); this->serializableType = new SerializableType(); } }; /*********************************************************************** EnumTypeDescriptor ***********************************************************************/ template class EnumValueType : public Object, public virtual IValueType { public: Value CreateDefault()override { return BoxValue(static_cast(0)); } IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override { auto ea = static_cast(UnboxValue(a)); auto eb = static_cast(UnboxValue(b)); if (ea < eb) return IBoxedValue::Smaller; if (ea > eb)return IBoxedValue::Greater; return IBoxedValue::Equal; } }; template class EnumType : public Object, public virtual IEnumType { protected: collections::Dictionary 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(candidates.Values()[index]); } vint IndexOfItem(WString name)override { return candidates.Keys().IndexOf(name); } Value ToEnum(vuint64_t value)override { return BoxValue(static_cast(value)); } vuint64_t FromEnum(const Value& value)override { return static_cast(UnboxValue(value)); } }; template class EnumTypeDescriptor : public TypedValueTypeDescriptorBase { using TEnumType = EnumType; protected: Ptr enumType; void LoadInternal()override { this->enumType = new TEnumType; this->valueType = new EnumValueType(); TypedValueTypeDescriptorBase::enumType = enumType; } }; /*********************************************************************** StructTypeDescriptor ***********************************************************************/ template class StructValueType : public Object, public virtual IValueType { public: Value CreateDefault()override { return BoxValue(T{}); } IBoxedValue::CompareResult Compare(const Value& a, const Value& b)override { return IBoxedValue::NotComparable; } }; template class StructTypeDescriptor : public TypedValueTypeDescriptorBase { protected: template class StructFieldInfo : public FieldInfoImpl { protected: TField T::* field; Value GetValueInternal(const Value& thisObject)override { auto structValue = thisObject.GetBoxedValue().Cast>(); if (!structValue) { throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject); } return BoxValue(structValue->value.*field); } void SetValueInternal(Value& thisObject, const Value& newValue)override { auto structValue = thisObject.GetBoxedValue().Cast>(); if (!structValue) { throw ArgumentTypeMismtatchException(L"thisObject", GetOwnerTypeDescriptor(), Value::BoxedValue, thisObject); } (structValue->value.*field) = UnboxValue(newValue); } public: StructFieldInfo(ITypeDescriptor* _ownerTypeDescriptor, TField T::* _field, const WString& _name) :field(_field) , FieldInfoImpl(_ownerTypeDescriptor, _name, TypeInfoRetriver::CreateTypeInfo()) { } IPropertyInfo::ICpp* GetCpp()override { return nullptr; } }; protected: collections::Dictionary> fields; public: StructTypeDescriptor() { this->valueType = new StructValueType(); } 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 struct ValueRetriver { T* pointer; }; template struct ValueRetriver { T* pointer; }; template struct TypeFlagTester { static const TypeFlags Result=TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(const Func* source){ return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::FunctionType:TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(const collections::LazyList* source){ return {}; } template static void* Inherit(const collections::IEnumerable* source) { return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::EnumerableType:TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(const collections::Array* source){ return {}; } template static void* Inherit(const collections::List* source) { return {}; } template static void* Inherit(const collections::SortedList* source) { return {}; } template static void* Inherit(const collections::ObservableListBase* source) { return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyListType:TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(collections::Array* source) { return {}; } static char Inherit(void* source) { return {}; } static char Inherit(const void* source) { return {}; } static const TypeFlags Result = sizeof(Inherit(((ValueRetriver*)0)->pointer)) == sizeof(void*) ? TypeFlags::ArrayType : TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(collections::List* source) { return {}; } template static void* Inherit(collections::ObservableListBase* source) { return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::ListType:TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(collections::ObservableList* source) { return {}; } static char Inherit(void* source) { return {}; } static char Inherit(const void* source) { return {}; } static const TypeFlags Result = sizeof(Inherit(((ValueRetriver*)0)->pointer)) == sizeof(void*) ? TypeFlags::ObservableListType : TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(const collections::Dictionary* source){ return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::ReadonlyDictionaryType:TypeFlags::NonGenericType; }; template struct TypeFlagTester { template static void* Inherit(collections::Dictionary* source){ return {}; } static char Inherit(void* source){ return {}; } static char Inherit(const void* source){ return {}; } static const TypeFlags Result=sizeof(Inherit(((ValueRetriver*)0)->pointer))==sizeof(void*)?TypeFlags::DictionaryType:TypeFlags::NonGenericType; }; /*********************************************************************** TypeFlagSelector ***********************************************************************/ template struct TypeFlagSelectorCase { static const TypeFlags Result=TypeFlags::NonGenericType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result=TypeFlags::FunctionType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result=TypeFlags::EnumerableType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result = TypeFlags::ReadonlyListType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result = TypeFlags::ArrayType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result = TypeFlags::ListType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result = TypeFlags::ObservableListType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result=TypeFlags::ReadonlyDictionaryType; }; template struct TypeFlagSelectorCase { static const TypeFlags Result=TypeFlags::DictionaryType; }; template struct TypeFlagSelector { static const TypeFlags Result = TypeFlagSelectorCase< T, (TypeFlags) ( (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result | (vint)TypeFlagTester::Result ) >::Result; }; /*********************************************************************** TypeHintTester ***********************************************************************/ template struct TypeHintTester { static const TypeInfoHint Result = TypeInfoHint::Normal; }; template struct TypeHintTesterForReference { static const TypeInfoHint Result = TypeInfoHint::NativeCollectionReference; }; template<> struct TypeHintTesterForReference { static const TypeInfoHint Result = TypeInfoHint::Normal; }; template<> struct TypeHintTesterForReference { static const TypeInfoHint Result = TypeInfoHint::Normal; }; template struct TypeHintTester { static const TypeInfoHint Result = TypeHintTester::Result; }; template struct TypeHintTester { static const TypeInfoHint Result = TypeHintTester::Result == TypeInfoHint::Normal ? TypeHintTesterForReference::Result>::Result : TypeHintTester::Result ; }; template struct TypeHintTester { static const TypeInfoHint Result = TypeHintTester::Result; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::LazyList; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::Array; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::List; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::SortedList; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::ObservableList; }; template struct TypeHintTester> { static const TypeInfoHint Result = TypeInfoHint::Dictionary; }; /*********************************************************************** DetailTypeInfoRetriver ***********************************************************************/ template struct DetailTypeInfoRetriver; /*********************************************************************** Basic Types ***********************************************************************/ template struct DetailTypeInfoRetriver { static const ITypeInfo::Decorator Decorator=ITypeInfo::TypeDescriptor; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { return MakePtr(GetTypeDescriptor(), hint); } #endif }; /*********************************************************************** Decorated Types ***********************************************************************/ template struct DetailTypeInfoRetriver { typedef DetailTypeInfoRetriver UpLevelRetriver; static const ITypeInfo::Decorator Decorator=ITypeInfo::RawPtr; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { return MakePtr(TypeInfoRetriver::CreateTypeInfo()); } #endif }; template struct DetailTypeInfoRetriver, TypeFlags::NonGenericType> { typedef DetailTypeInfoRetriver UpLevelRetriver; static const ITypeInfo::Decorator Decorator=ITypeInfo::SharedPtr; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { return MakePtr(TypeInfoRetriver::CreateTypeInfo()); } #endif }; template struct DetailTypeInfoRetriver, TypeFlags::NonGenericType> { typedef DetailTypeInfoRetriver UpLevelRetriver; static const ITypeInfo::Decorator Decorator=ITypeInfo::Nullable; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { return MakePtr(TypeInfoRetriver::CreateTypeInfo()); } #endif }; /*********************************************************************** Containers ***********************************************************************/ template struct DetailTypeInfoRetriver_Template1 { typedef DetailTypeInfoRetriver UpLevelRetriver; static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { auto arrayType = MakePtr(GetTypeDescriptor(), hint); auto genericType = MakePtr(arrayType); genericType->AddGenericArgument(TypeInfoRetriver::CreateTypeInfo()); auto type = MakePtr(genericType); return type; } #endif }; template struct DetailTypeInfoRetriver_Template2 { typedef DetailTypeInfoRetriver UpLevelRetriver; static const ITypeInfo::Decorator Decorator = UpLevelRetriver::Decorator; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { auto arrayType = MakePtr(GetTypeDescriptor(), hint); auto genericType = MakePtr(arrayType); genericType->AddGenericArgument(TypeInfoRetriver::CreateTypeInfo()); genericType->AddGenericArgument(TypeInfoRetriver::CreateTypeInfo()); auto type = MakePtr(genericType); return type; } #endif }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template1 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template1 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template1 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template1 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template1 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template2 { }; template struct DetailTypeInfoRetriver : DetailTypeInfoRetriver_Template2 { }; /*********************************************************************** Functions ***********************************************************************/ #ifndef VCZH_DEBUG_NO_REFLECTION namespace internal_helper { template struct GenericArgumentAdder { static void Add(Ptr genericType) { } }; template struct GenericArgumentAdder> { static void Add(Ptr genericType) { genericType->AddGenericArgument(TypeInfoRetriver::CreateTypeInfo()); GenericArgumentAdder>::Add(genericType); } }; } #endif template struct DetailTypeInfoRetriver, TypeFlags::FunctionType> { typedef DetailTypeInfoRetriver, TypeFlags::NonGenericType> UpLevelRetriver; static const ITypeInfo::Decorator Decorator=UpLevelRetriver::Decorator; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo(TypeInfoHint hint) { auto functionType = MakePtr(GetTypeDescriptor(), hint); auto genericType = MakePtr(functionType); genericType->AddGenericArgument(TypeInfoRetriver::CreateTypeInfo()); internal_helper::GenericArgumentAdder>::Add(genericType); auto type = MakePtr(genericType); return type; } #endif }; /*********************************************************************** TypeInfoRetriver ***********************************************************************/ template struct TypeInfoRetriver { static const TypeFlags TypeFlag = TypeFlagSelector::Result; static const TypeInfoHint Hint = TypeHintTester::Result; typedef DetailTypeInfoRetriver, TypeFlag> Detail; static const ITypeInfo::Decorator Decorator = Detail::Decorator; #ifndef VCZH_DEBUG_NO_REFLECTION static Ptr CreateTypeInfo() { return DetailTypeInfoRetriver, TypeFlag>::CreateTypeInfo(Hint); } #endif }; template<> struct TypeInfoRetriver : public TypeInfoRetriver { }; } } } #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 struct ValueAccessor { }; /// Box an reflectable object. Its type cannot be generic. /// The boxed value. /// Type of the object. /// The object to box. /// The type descriptor of the object (optional). template Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor) { using Type = std::remove_cvref_t; return ValueAccessor::Decorator>::BoxValue(object, typeDescriptor); } /// Unbox a reflectable object. Its type cannot be generic. /// The unboxed object. /// Type of the object. /// The value to unbox. /// The type descriptor of the object (optional). /// The name of the object to provide a friendly exception message if the conversion is failed (optional). template T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { using Type = std::remove_cvref_t; return ValueAccessor::Decorator>::UnboxValue(value, typeDescriptor, valueName); } /*********************************************************************** Basic Types ***********************************************************************/ template struct ValueAccessor { 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(); } if(!result) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(!typeDescriptor) { typeDescriptor=GetTypeDescriptor(); } throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::RawPtr, value); #else CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch."); #endif } return result; } }; template struct ValueAccessor, ITypeInfo::SharedPtr> { static Value BoxValue(Ptr object, ITypeDescriptor* typeDescriptor) { return Value::From(object); } static Ptr UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { if (value.IsNull()) return nullptr; Ptr result; if(value.GetValueType()==Value::RawPtr || value.GetValueType()==Value::SharedPtr) { result = value.GetRawPtr()->SafeAggregationCast(); } if(!result) { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(!typeDescriptor) { typeDescriptor=GetTypeDescriptor(); } throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::SharedPtr, value); #else CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch."); #endif } return result; } }; template struct ValueAccessor, ITypeInfo::Nullable> { static Value BoxValue(Nullable object, ITypeDescriptor* typeDescriptor) { return object?ValueAccessor::BoxValue(object.Value(), typeDescriptor):Value(); } static Nullable UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { if(value.IsNull()) { return Nullable(); } else { return ValueAccessor::UnboxValue(value, typeDescriptor, valueName); } } }; template struct ValueAccessor { static Value BoxValue(const T& object, ITypeDescriptor* typeDescriptor) { using Type = std::remove_cvref_t; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if(!typeDescriptor) { typeDescriptor = GetTypeDescriptor(); } #endif return Value::From(new IValueType::TypedBox(object), typeDescriptor); } static T UnboxValue(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { using Type = std::remove_cvref_t; if (auto unboxedValue = value.GetBoxedValue().Cast>()) { return unboxedValue->value; } else { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA if (!typeDescriptor) { typeDescriptor = GetTypeDescriptor(); } throw ArgumentTypeMismtatchException(valueName, typeDescriptor, Value::BoxedValue, value); #else CHECK_FAIL(L"vl::reflection::description::UnboxValue()#Argument type mismatch."); #endif } } }; template<> struct ValueAccessor { 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 { 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 struct ParameterAccessor { }; /// Box an reflectable object. It supports generic types such as containers, functions (should be Func<T>), etc. /// The boxed value. /// Type of the object. /// The object to box. /// The type descriptor of the object (optional). template Value BoxParameter(T&& object, ITypeDescriptor* typeDescriptor) { using TIR = TypeInfoRetriver>; return ParameterAccessor, TIR::TypeFlag>::BoxParameter(object, typeDescriptor); } /// Box an reflectable object. It supports generic types such as containers, functions (should be Func<T>), etc. /// Type of the object. /// The unboxed object. It could be the same object that is boxed, or it could be a new object. /// The value to unbox. /// The type descriptor of the object (optional). /// The name of the object to provide a friendly exception message if the conversion is failed (optional). template Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor , const WString& valueName) { using TIR = TypeInfoRetriver>; return ParameterAccessor::UnboxParameter(value, typeDescriptor, valueName); } /*********************************************************************** BoxParametersToList ***********************************************************************/ inline void BoxParametersToList(Ptr arguments) {} template void BoxParametersToList(Ptr arguments, T0&& p0, TArgs&& ...args) { arguments->Add(description::BoxParameter(p0)); BoxParametersToList(arguments, args...); } class Value_xs { protected: collections::Array arguments; public: Value_xs() { } template 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& () { return arguments; } }; /*********************************************************************** Basic Types ***********************************************************************/ template struct ParameterAccessor { static Value BoxParameter(const T& object, ITypeDescriptor* typeDescriptor) { return BoxValue(object, typeDescriptor); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return { new T(std::move(UnboxValue(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 struct ArgPack { using TArg = T; static const vint Index = I; }; template struct ArgPacks { }; template struct MakeArgPacks_; template struct MakeArgPacks_> { using Type = ArgPacks; }; template struct MakeArgPacks_, T0, TArgs...> { using Type = typename MakeArgPacks_>, TArgs...>::Type; }; } template using MakeArgPacks = typename unboxcall_helper::MakeArgPacks_, TArgs...>::Type; namespace unboxcall_helper { template struct Unbox; template struct Unbox> { template static auto AndCallObject(TFunction&& function, IMethodInfo* methodInfo, const Ptr& arguments) -> decltype(function(std::declval()...)) { // function(arguments) return function(UnboxParameter>( arguments->Get(TArgPacks::Index), (methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr) ).Ref()...); } template static auto AndCallFunction(TFunction function, IMethodInfo* methodInfo, collections::Array& arguments) -> decltype(function(std::declval()...)) { // function(arguments) return function(UnboxParameter>( arguments[TArgPacks::Index], (methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr) ).Ref()...); } template static auto AndCallMethod(TFunction function, IMethodInfo* methodInfo, collections::Array& arguments, TClass* object) -> decltype((object->*function)(std::declval()...)) { // (object->*function)(arguments) return (object->*function)(UnboxParameter>( arguments[TArgPacks::Index], (methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr) ).Ref()...); } template static auto AndCallExternal(TFunction function, IMethodInfo* methodInfo, collections::Array& arguments, TClass* object) -> decltype(function(object, std::declval()...)) { // function(object, arguments) return function( object, UnboxParameter>( arguments[TArgPacks::Index], (methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr) ).Ref()... ); } template static R AndNew(IMethodInfo* methodInfo, collections::Array& arguments) { // new TClass(arguments) return R(new TClass(UnboxParameter>( arguments[TArgPacks::Index], (methodInfo ? methodInfo->GetParameter(TArgPacks::Index)->GetType()->GetTypeDescriptor() : nullptr) ).Ref()...)); } }; } /*********************************************************************** Invoke ***********************************************************************/ namespace invoke_helper { template Value InvokeMethod(TClass* object, R(__thiscall TClass::* method)(TArgs...), IMethodInfo* methodInfo, collections::Array& arguments) { using TArgPacks = MakeArgPacks; if constexpr (std::is_same_v) { unboxcall_helper::Unbox::AndCallMethod(method, methodInfo, arguments, object); return {}; } else { auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr; return BoxParameter(unboxcall_helper::Unbox::AndCallMethod(method, methodInfo, arguments, object), td); } } template Value InvokeExternal(TClass* object, R(*method)(TClass*, TArgs...), IMethodInfo* methodInfo, collections::Array& arguments) { using TArgPacks = MakeArgPacks; if constexpr (std::is_same_v) { unboxcall_helper::Unbox::AndCallExternal(method, methodInfo, arguments, object); return {}; } else { auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr; return BoxParameter(unboxcall_helper::Unbox::AndCallExternal(method, methodInfo, arguments, object), td); } } template Value InvokeFunction(R(*method)(TArgs...), IMethodInfo* methodInfo, collections::Array& arguments) { using TArgPacks = MakeArgPacks; if constexpr (std::is_same_v) { unboxcall_helper::Unbox::AndCallFunction(method, methodInfo, arguments); return {}; } else { auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr; return BoxParameter(unboxcall_helper::Unbox::AndCallFunction(method, methodInfo, arguments), td); } } template Value InvokeObject(TFunction& function, IMethodInfo* methodInfo, const Ptr& arguments) { using TArgPacks = MakeArgPacks; using TResult = decltype(unboxcall_helper::Unbox::AndCallObject(function, methodInfo, arguments)); if constexpr (std::is_same_v) { unboxcall_helper::Unbox::AndCallObject(function, methodInfo, arguments); return {}; } else { auto td = methodInfo ? methodInfo->GetReturn()->GetTypeDescriptor() : nullptr; return BoxParameter(unboxcall_helper::Unbox::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 class TypedEnumerator : public Object, public collections::IEnumerator { private: Ptr enumerable; Ptr enumerator; vint index; T value; public: TypedEnumerator(Ptr _enumerable, vint _index, const T& _value) :enumerable(_enumerable) ,index(_index) ,value(_value) { enumerator=enumerable->CreateEnumerator(); vint current=-1; while(current++Next(); } } TypedEnumerator(Ptr _enumerable) :enumerable(_enumerable) ,index(-1) { Reset(); } collections::IEnumerator* Clone()const override { return new TypedEnumerator(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(enumerator->GetCurrent()); return true; } else { return false; } } void Reset() override { index=-1; enumerator=enumerable->CreateEnumerator(); } }; /// Convert a reflectable container to a lazy list to the known element type. /// The created lazy list. /// The expected element type. /// The reflectable container. template collections::LazyList GetLazyList(Ptr value) { return collections::LazyList(new TypedEnumerator(value)); } /// Convert a reflectable container to a lazy list to the known element type. /// The created lazy list. /// The expected element type. /// The reflectable container. template collections::LazyList GetLazyList(Ptr value) { return collections::Range(0, value->GetCount()) .Select([value](vint i) { return UnboxValue(value->Get(i)); }); } /// Convert a reflectable container to a lazy list to the known element type. /// The created lazy list. /// The expected element type. /// The reflectable container. template collections::LazyList GetLazyList(Ptr value) { return GetLazyList(Ptr(value)); } /// Convert a reflectable container to a lazy list to the known element type. /// The created lazy list. /// The expected element type. /// The reflectable container. template collections::LazyList GetLazyList(Ptr value) { return GetLazyList(Ptr(value)); } /// Convert a reflectable container to a lazy list to the known element type. /// The created lazy list. /// The expected element type. /// The reflectable container. template collections::LazyList GetLazyList(Ptr value) { return GetLazyList(Ptr(value)); } /// Convert a reflectable dictionary to a lazy list to the known element type. /// The created lazy list. /// The expected key type. /// The expected value type. /// The reflectable dictionary. template collections::LazyList> GetLazyList(Ptr value) { return collections::Range(0, value->GetCount()) .Select([value](vint i) { return collections::Pair(UnboxValue(value->GetKeys()->Get(i)), UnboxValue(value->GetValues()->Get(i))); }); } /// Convert a reflectable dictionary to a lazy list to the known element type. /// The created lazy list. /// The expected key type. /// The expected value type. /// The reflectable dictionary. template collections::LazyList> GetLazyList(Ptr value) { return GetLazyList(Ptr(value)); } /*********************************************************************** Collection Wrappers ***********************************************************************/ namespace trait_helper { template struct RemovePtr { typedef T Type; }; template struct RemovePtr { typedef T Type; }; template struct RemovePtr> { typedef T Type; }; } #pragma warning(push) #pragma warning(disable:4250) template class ValueEnumerableWrapper; template class ValueEnumeratorWrapper : public Object, public virtual IValueEnumerator { protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::ElementType ElementType; Ptr enumerableWrapper; TEnumerator wrapperPointer; public: ValueEnumeratorWrapper(const Ptr& _enumerableWrapper, const TEnumerator& _wrapperPointer) :enumerableWrapper(_enumerableWrapper) , wrapperPointer(_wrapperPointer) { } Value GetCurrent()override { if (!enumerableWrapper->wrapperPointer) throw ObjectDisposedException(); return BoxValue(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 class ValueEnumerableWrapper : public Object, public virtual collections::ICollectionReference, public virtual IValueEnumerable { template friend class ValueEnumeratorWrapper; protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::ElementType ElementType; T wrapperPointer; public: ValueEnumerableWrapper(const T& _wrapperPointer) :wrapperPointer(_wrapperPointer) { } void OnDisposed()override { wrapperPointer = nullptr; } Ptr CreateEnumerator()override { ENSURE_WRAPPER_POINTER; return new ValueEnumeratorWrapper< ValueEnumerableWrapper, Ptr> >( this, wrapperPointer->CreateEnumerator() ); } const Object* GetCollectionObject()override { if constexpr (std::is_same_v::Type*, T>) { if (wrapperPointer->GetCollectionReference() == this) { return wrapperPointer; } else { return nullptr; } } else { return nullptr; } } }; template class ValueReadonlyListWrapper : public ValueEnumerableWrapper, public virtual IValueReadonlyList { protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::ElementType ElementType; typedef typename KeyType::Type ElementKeyType; public: ValueReadonlyListWrapper(const T& _wrapperPointer) :ValueEnumerableWrapper(_wrapperPointer) { } vint GetCount()override { ENSURE_WRAPPER_POINTER; return WRAPPER_POINTER->Count(); } Value Get(vint index)override { ENSURE_WRAPPER_POINTER; return BoxValue(WRAPPER_POINTER->Get(index)); } bool Contains(const Value& value)override { ENSURE_WRAPPER_POINTER; ElementKeyType item = UnboxValue(value); return WRAPPER_POINTER->Contains(item); } vint IndexOf(const Value& value)override { ENSURE_WRAPPER_POINTER; ElementKeyType item = UnboxValue(value); return WRAPPER_POINTER->IndexOf(item); } }; template class ValueArrayWrapper : public ValueReadonlyListWrapper, public virtual IValueArray { protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::ElementType ElementType; typedef typename KeyType::Type ElementKeyType; public: ValueArrayWrapper(const T& _wrapperPointer) :ValueReadonlyListWrapper(_wrapperPointer) { } void Set(vint index, const Value& value)override { ENSURE_WRAPPER_POINTER; ElementType item = UnboxValue(value); WRAPPER_POINTER->Set(index, item); } void Resize(vint size)override { ENSURE_WRAPPER_POINTER; return WRAPPER_POINTER->Resize(size); } }; template class ValueListWrapper : public ValueReadonlyListWrapper, public virtual IValueList { protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::ElementType ElementType; typedef typename KeyType::Type ElementKeyType; public: ValueListWrapper(const T& _wrapperPointer) :ValueReadonlyListWrapper(_wrapperPointer) { } void Set(vint index, const Value& value)override { ENSURE_WRAPPER_POINTER; ElementType item = UnboxValue(value); WRAPPER_POINTER->Set(index, item); } vint Add(const Value& value)override { ENSURE_WRAPPER_POINTER; ElementType item = UnboxValue(value); return WRAPPER_POINTER->Add(item); } vint Insert(vint index, const Value& value)override { ENSURE_WRAPPER_POINTER; ElementType item = UnboxValue(value); return WRAPPER_POINTER->Insert(index, item); } bool Remove(const Value& value)override { ENSURE_WRAPPER_POINTER; ElementKeyType item = UnboxValue(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 class ValueObservableListWrapper : public ValueListWrapper, public virtual IValueObservableList { public: ValueObservableListWrapper(const T& _wrapperPointer) :ValueListWrapper(_wrapperPointer) { } }; template class ValueReadonlyDictionaryWrapper : public virtual Object, public virtual collections::ICollectionReference, public virtual IValueReadonlyDictionary { protected: typedef typename trait_helper::RemovePtr::Type ContainerType; typedef typename ContainerType::KeyContainer KeyContainer; typedef typename ContainerType::ValueContainer ValueContainer; typedef typename KeyContainer::ElementType KeyValueType; typedef typename KeyType::Type KeyKeyType; typedef typename ValueContainer::ElementType ValueType; T wrapperPointer; Ptr keys; Ptr values; public: ValueReadonlyDictionaryWrapper(const T& _wrapperPointer) :wrapperPointer(_wrapperPointer) { } void OnDisposed()override { wrapperPointer = nullptr; keys = nullptr; values = nullptr; } Ptr GetKeys()override { ENSURE_WRAPPER_POINTER; if (!keys) { keys = UnboxValue>(BoxParameter(wrapperPointer->Keys())); } return keys; } Ptr GetValues()override { ENSURE_WRAPPER_POINTER; if (!values) { values = UnboxValue>(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(key); ValueType result = wrapperPointer->Get(item); return BoxValue(result); } const Object* GetCollectionObject()override { if constexpr (std::is_same_v::Type*, T>) { if (wrapperPointer->GetCollectionReference() == this) { return wrapperPointer; } else { return nullptr; } } else { return nullptr; } } }; #define KEY_VALUE_TYPE typename ValueReadonlyDictionaryWrapper::KeyValueType #define VALUE_TYPE typename ValueReadonlyDictionaryWrapper::ValueType #define KEY_KEY_TYPE typename ValueReadonlyDictionaryWrapper::KeyKeyType template class ValueDictionaryWrapper : public virtual ValueReadonlyDictionaryWrapper, public virtual IValueDictionary { public: ValueDictionaryWrapper(const T& _wrapperPointer) :ValueReadonlyDictionaryWrapper(_wrapperPointer) { } void Set(const Value& key, const Value& value)override { ENSURE_WRAPPER_POINTER; KEY_VALUE_TYPE item = UnboxValue(key); VALUE_TYPE result = UnboxValue(value); WRAPPER_POINTER->Set(item, result); } bool Remove(const Value& key)override { ENSURE_WRAPPER_POINTER; KEY_KEY_TYPE item = UnboxValue(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 void ObservableList::NotifyUpdateInternal(vint start, vint count, vint newCount) { if (auto colref = this->template TryGetCollectionReference()) { 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 class TValueImpl, typename T> auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t, Ptr> { auto colref = collection->template TryGetCollectionReference>(); if (colref) return colref; colref = MakePtr>(collection); collection->SetCollectionReference(colref); return colref; } template class TValueImpl, typename T> auto GetValueCollectionFromCollection(T* collection) -> std::enable_if_t, Ptr> { #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA throw ArgumentTypeMismtatchException( WString::Unmanaged(L"collection"), Description::GetAssociatedTypeDescriptor(), Description::GetAssociatedTypeDescriptor() ); #else CHECK_FAIL(L"vl::reflection::description::GetValueCollectionFromCollection()#Argument type mismatch."); #endif } template Ptr ChooseValueCollectionFromNonDictionaryEnumerable(const collections::IEnumerable* enumerable) { auto writable = const_cast(enumerable->GetCollectionObject()); if (auto xs = dynamic_cast>*>(writable)) { return GetValueCollectionFromCollection(xs); } else if (auto xs = dynamic_cast>*>(writable)) { return GetValueCollectionFromCollection(xs); } else if (auto xs = dynamic_cast>*>(writable)) { return GetValueCollectionFromCollection(xs); } else if (auto xs = dynamic_cast>*>(writable)) { return GetValueCollectionFromCollection(xs); } else if (auto xs = dynamic_cast>*>(writable)) { return GetValueCollectionFromCollection(xs); } else { return GetValueCollectionFromCollection(xs); } } template Ptr ChooseValueCollectionFromEnumerable(const collections::IEnumerable* enumerable) { return ChooseValueCollectionFromNonDictionaryEnumerable(enumerable); } template Ptr ChooseValueCollectionFromEnumerable(const collections::IEnumerable>* enumerable) { auto writable = const_cast(enumerable->GetCollectionObject()); if (auto xs = dynamic_cast, std::remove_cvref_t>*>(writable)) { return GetValueCollectionFromCollection(xs); } else { return ChooseValueCollectionFromNonDictionaryEnumerable(enumerable); } } template Value GetValueFromEnumerable(const collections::IEnumerable& enumerable) { auto result = ChooseValueCollectionFromEnumerable(&enumerable); ITypeDescriptor* td = nullptr; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA td = Description::GetAssociatedTypeDescriptor(); #endif return BoxValue(result, td); } template Unboxed UnboxCollection(const Ptr& colref) { using TCollection = std::remove_const_t; if (auto colobj = dynamic_cast(const_cast(colref->GetCollectionObject()))) { return { colobj,false }; } else { auto collection = new TCollection(); auto lazyList = GetLazyList(colref); collections::CopyFrom(*collection, lazyList); return { collection, true }; } } template Unboxed UnboxDictionary(const Ptr& colref) { using TCollection = std::remove_const_t; if (auto colobj = dynamic_cast(const_cast(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 struct ParameterAccessor, TypeFlags::EnumerableType> { static Value BoxParameter(const collections::LazyList& object, ITypeDescriptor* typeDescriptor) { Ptr result = IValueEnumerable::Create( collections::From(object) .Select([](const T& item) { return BoxValue(item); }) ); ITypeDescriptor* td = nullptr; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA td = Description::GetAssociatedTypeDescriptor(); #endif return BoxValue(result, td); } }; template struct ParameterAccessor, TypeFlags::EnumerableType> { static Value BoxParameter(collections::LazyList& object, ITypeDescriptor* typeDescriptor) { return ParameterAccessor, TypeFlags::EnumerableType>::BoxParameter(object, typeDescriptor); } static Unboxed> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { typedef typename collections::LazyList::ElementType ElementType; Ptr listProxy = UnboxValue>(value, typeDescriptor, valueName); return { new collections::LazyList(std::move(GetLazyList(listProxy))), true }; } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxCollection(UnboxValue>(value, typeDescriptor, valueName)); } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxCollection(UnboxValue>(value, typeDescriptor, valueName)); } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxCollection(UnboxValue>(value, typeDescriptor, valueName)); } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxCollection(UnboxValue>(value, typeDescriptor, valueName)); } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxDictionary(UnboxValue>(value, typeDescriptor, valueName)); } }; template struct ParameterAccessor { static Value BoxParameter(T& object, ITypeDescriptor* typeDescriptor) { return GetValueFromEnumerable(object); } static Unboxed UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { return UnboxDictionary(UnboxValue>(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 class ValueFunctionProxyWrapper { }; template class ValueFunctionProxyWrapper : public Object, public virtual IValueFunctionProxy { typedef Func FunctionType; protected: FunctionType function; public: ValueFunctionProxyWrapper(const FunctionType& _function) :function(_function) { } FunctionType GetFunction() { return function; } Value Invoke(Ptr 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(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 struct ParameterAccessor, TypeFlags::FunctionType> { static Value BoxParameter(const Func& object, ITypeDescriptor* typeDescriptor) { typedef R(RawFunctionType)(TArgs...); Ptr result=new ValueFunctionProxyWrapper(object); ITypeDescriptor* td = nullptr; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA td = Description::GetAssociatedTypeDescriptor(); #endif return BoxValue>(result, td); } static Unboxed> UnboxParameter(const Value& value, ITypeDescriptor* typeDescriptor, const WString& valueName) { typedef R(RawFunctionType)(TArgs...); typedef Func FunctionType; typedef ValueFunctionProxyWrapper ProxyType; if (auto functionProxy = UnboxValue>(value, typeDescriptor, valueName)) { if (auto proxy = functionProxy.Cast()) { return { new FunctionType(std::move(proxy->GetFunction())), true }; } else { return { new FunctionType([functionProxy](TArgs ...args) { Ptr arguments = IValueList::Create(); BoxParametersToList(arguments, std::forward(args)...); auto result = functionProxy->Invoke(arguments); if constexpr (!std::is_same_v) { auto unboxed = description::UnboxParameter>(result); if (std::is_reference_v) { 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 struct ParameterAccessor, TypeFlags::FunctionType> : ParameterAccessor, 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 struct ConstructorArgumentAdder { static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index) { } }; template struct ConstructorArgumentAdder> { static void Add(MethodInfoImpl* methodInfo, const wchar_t* parameterNames[], vint index) { methodInfo->AddParameter(new ParameterInfoImpl(methodInfo, parameterNames[index], TypeInfoRetriver::CreateTypeInfo())); ConstructorArgumentAdder>::Add(methodInfo, parameterNames, index + 1); } }; } /*********************************************************************** MethodInfoImpl ***********************************************************************/ template class CustomConstructorInfoImpl{}; template class CustomMethodInfoImpl{}; template class CustomExternalMethodInfoImpl{}; template class CustomStaticMethodInfoImpl{}; template 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 struct EventHelper { using Handler = const Func&; class EventHandlerImpl : public Object, public reflection::description::IEventHandler { public: Ptr handler; EventHandlerImpl(Ptr _handler) :handler(_handler) { } bool IsAttached()override { return handler->IsAttached(); } }; static Ptr Attach(Event& e, Handler handler) { return MakePtr(e.Add(handler)); } static bool Detach(Event& e, Ptr handler) { auto impl = handler.Cast(); if (!impl) return false; return e.Remove(impl->handler); } static Event& Invoke(Event& e) { return e; } }; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA /*********************************************************************** CustomEventInfoImpl ***********************************************************************/ template class CustomEventInfoImpl : public EventInfoImpl { protected: Event TClass::* eventRef; Ptr AttachInternal(DescriptableObject* thisObject, Ptr handler)override { TClass* object = UnboxValue(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject"); Event& eventObject = object->*eventRef; auto func = Func([=](TArgs ...args) { auto arguments = IValueList::Create(); BoxParametersToList(arguments, std::forward(args)...); handler->Invoke(arguments); }); return EventHelper::Attach(eventObject, func); } bool DetachInternal(DescriptableObject* thisObject, Ptr handler)override { TClass* object = UnboxValue(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject"); Event& eventObject = object->*eventRef; return EventHelper::Detach(eventObject, handler); } void InvokeInternal(DescriptableObject* thisObject, Ptr arguments)override { TClass* object = UnboxValue(Value::From(thisObject), GetOwnerTypeDescriptor(), L"thisObject"); Event& eventObject = object->*eventRef; invoke_helper::InvokeObject, TArgs...>(eventObject, nullptr, arguments); } Ptr GetHandlerTypeInternal()override { return TypeInfoRetriver>::CreateTypeInfo(); } public: CustomEventInfoImpl(ITypeDescriptor* _ownerTypeDescriptor, const WString& _name, Event TClass::* _eventRef) :EventInfoImpl(_ownerTypeDescriptor, _name) , eventRef(_eventRef) { } ~CustomEventInfoImpl() { } IEventInfo::ICpp* GetCpp()override { return nullptr; } }; template struct CustomEventFunctionTypeRetriver { typedef vint Type; }; template struct CustomEventFunctionTypeRetriver 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 ***********************************************************************/ template class CustomConstructorInfoImpl : public MethodInfoImpl { using TClass = typename trait_helper::RemovePtr>::Type; protected: Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override { return BoxParameter(unboxcall_helper::Unbox>::template AndNew(this, arguments)); } Value CreateFunctionProxyInternal(const Value& thisObject)override { Func proxy( LAMBDA([](TArgs ...args)->R { R result = new TClass(args...); return result; }) ); return BoxParameter(proxy); } public: CustomConstructorInfoImpl(const wchar_t* parameterNames[]) :MethodInfoImpl(0, TypeInfoRetriver::CreateTypeInfo(), true) { internal_helper::ConstructorArgumentAdder>::Add(this, parameterNames, 0); } IMethodInfo::ICpp* GetCpp()override { return nullptr; } }; /*********************************************************************** CustomMethodInfoImpl CustomExternalMethodInfoImpl ***********************************************************************/ 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 _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 class CustomMethodInfoImpl : public MethodInfoImpl_StaticCpp { protected: R(__thiscall TClass::* method)(TArgs...); Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override { TClass* object = UnboxValue(thisObject, GetOwnerTypeDescriptor(), L"thisObject"); return invoke_helper::InvokeMethod(object, method, this, arguments); } Value CreateFunctionProxyInternal(const Value& thisObject)override { TClass* object = UnboxValue(thisObject, GetOwnerTypeDescriptor(), L"thisObject"); Func 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::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate) , method(_method) { internal_helper::ConstructorArgumentAdder>::Add(this, parameterNames, 0); } }; template class CustomExternalMethodInfoImpl : public MethodInfoImpl_StaticCpp { protected: R(*method)(TClass*, TArgs...); Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override { TClass* object = UnboxValue(thisObject, GetOwnerTypeDescriptor(), L"thisObject"); return invoke_helper::InvokeExternal(object, method, this, arguments); } Value CreateFunctionProxyInternal(const Value& thisObject)override { TClass* object = UnboxValue(thisObject, GetOwnerTypeDescriptor(), L"thisObject"); Func proxy = Curry(Func(method))(object); 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::CreateTypeInfo(), false, _invokeTemplate, _closureTemplate) , method(_method) { internal_helper::ConstructorArgumentAdder>::Add(this, parameterNames, 0); } }; /*********************************************************************** CustomStaticMethodInfoImpl ***********************************************************************/ template class CustomStaticMethodInfoImpl : public MethodInfoImpl_StaticCpp { protected: R(* method)(TArgs...); Value InvokeInternal(const Value& thisObject, collections::Array& arguments)override { return invoke_helper::InvokeFunction(method, this, arguments); } Value CreateFunctionProxyInternal(const Value& thisObject)override { Func 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::CreateTypeInfo(), true, _invokeTemplate, _closureTemplate) ,method(_method) { internal_helper::ConstructorArgumentAdder>::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 struct CustomTypeDescriptorSelector{}; struct MethodPointerBinaryData { typedef collections::Dictionary MethodMap; class IIndexer : public virtual IDescriptable { public: virtual void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo) = 0; virtual IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data) = 0; }; vint data[4]; static inline vint Compare(const MethodPointerBinaryData& a, const MethodPointerBinaryData& b) { { auto result = a.data[0] - b.data[0]; if (result != 0) return result; } { auto result = a.data[1] - b.data[1]; if (result != 0) return result; } { auto result = a.data[2] - b.data[2]; if (result != 0) return result; } { auto result = a.data[3] - b.data[3]; if (result != 0) return result; } return 0; } #define COMPARE(OPERATOR)\ inline bool operator OPERATOR(const MethodPointerBinaryData& d)const\ {\ return Compare(*this, d) OPERATOR 0;\ } COMPARE(<) COMPARE(<=) COMPARE(>) COMPARE(>=) COMPARE(==) COMPARE(!=) #undef COMPARE }; template 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 struct MethodPointerBinaryDataRecorder { static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo) { } }; template struct MethodPointerBinaryDataRecorder { static void RecordMethod(const MethodPointerBinaryData& data, ITypeDescriptor* td, IMethodInfo* methodInfo) { auto impl = dynamic_cast(td); CHECK_ERROR(impl != nullptr, L"Internal error: RecordMethod can only be called when registering methods."); impl->IndexMethodInfo(data, methodInfo); } }; template using FUNCTIONNAME_AddPointer = T*; /*********************************************************************** Type ***********************************************************************/ #define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{ #define END_TYPE_INFO_NAMESPACE }}} #define ADD_TYPE_INFO(TYPENAME)\ {\ Ptr type=new CustomTypeDescriptorSelector::CustomTypeDescriptorImpl();\ manager->SetTypeDescriptor(TypeInfo::content.typeName, type);\ } /*********************************************************************** InterfaceProxy ***********************************************************************/ #define INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\ static INTERFACE* Create(Ptr proxy)\ {\ auto obj = new ValueInterfaceProxy();\ obj->SetProxy(proxy);\ return obj;\ }\ #define INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\ static Ptr Create(Ptr proxy)\ {\ auto obj = new ValueInterfaceProxy();\ obj->SetProxy(proxy);\ return obj;\ }\ #define BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\ template<>\ class ValueInterfaceProxy : public ValueInterfaceImpl\ {\ 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 : public ValueInterfaceImpl\ {\ 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 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(this)->GetTypeDescriptor())\ {\ _interface_proxy_typeDescriptor = static_cast(this)->GetTypeDescriptor();\ CHECK_ERROR(_interface_proxy_typeDescriptor != nullptr, L"Internal error: The type of this interface has not been registered.");\ auto impl = dynamic_cast(_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 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_xs(), __VA_ARGS__)))) #define INVOKE_INTERFACE_PROXY_NOPARAMS(METHODNAME)\ PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\ proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create()) #define INVOKEGET_INTERFACE_PROXY(METHODNAME, ...)\ PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\ return UnboxValue(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array&)(Value_xs(), __VA_ARGS__))))) #define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\ PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\ return UnboxValue(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())) /*********************************************************************** Enum ***********************************************************************/ #define BEGIN_ENUM_ITEM_FLAG(TYPENAME, TDFLAGS)\ template<>\ struct CustomTypeDescriptorSelector\ {\ public:\ class CustomTypeDescriptorImpl : public EnumTypeDescriptor\ {\ typedef TYPENAME EnumType;\ public:\ void LoadInternal()override\ {\ EnumTypeDescriptor::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\ {\ public:\ class CustomTypeDescriptorImpl : public StructTypeDescriptor\ {\ typedef TYPENAME StructType;\ protected:\ void LoadInternal()override\ { #define BEGIN_STRUCT_MEMBER(TYPENAME)\ BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TypeDescriptorFlags::Struct) #define END_STRUCT_MEMBER(TYPENAME)\ }\ };\ }; #define STRUCT_MEMBER(FIELDNAME)\ fields.Add(L ## #FIELDNAME, new StructFieldInfoFIELDNAME)>(this, &StructType::FIELDNAME, L ## #FIELDNAME)); /*********************************************************************** Class ***********************************************************************/ #define BEGIN_CLASS_MEMBER(TYPENAME)\ template<>\ struct CustomTypeDescriptorSelector\ {\ public:\ class CustomTypeDescriptorImpl : public TypeDescriptorImpl\ {\ typedef TYPENAME ClassType;\ static const TypeDescriptorFlags TDFlags = TypeDescriptorFlags::Class;\ public:\ CustomTypeDescriptorImpl()\ :TypeDescriptorImpl(TDFlags, &TypeInfo::content)\ {\ Description::SetAssociatedTypeDescriptor(this);\ }\ ~CustomTypeDescriptorImpl()\ {\ Description::SetAssociatedTypeDescriptor(0);\ }\ protected:\ bool IsAggregatable()override\ {\ return std::is_convertible_v*>;\ }\ void LoadInternal()override\ { #define CLASS_MEMBER_BASE(TYPENAME)\ AddBaseType(description::GetTypeDescriptor()); #define END_CLASS_MEMBER(TYPENAME)\ if (GetBaseTypeDescriptorCount() == 0) CLASS_MEMBER_BASE(DescriptableObject)\ }\ };\ }; /*********************************************************************** Interface ***********************************************************************/ #define BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TDFLAGS)\ template<>\ struct CustomTypeDescriptorSelector\ {\ public:\ class CustomTypeDescriptorImpl : public TypeDescriptorImpl, public MethodPointerBinaryData::IIndexer\ {\ typedef TYPENAME ClassType;\ static const TypeDescriptorFlags TDFlags = TDFLAGS;\ MethodPointerBinaryData::MethodMap methodsForProxy;\ public:\ CustomTypeDescriptorImpl()\ :TypeDescriptorImpl(TDFLAGS, &TypeInfo::content)\ {\ Description::SetAssociatedTypeDescriptor(this);\ }\ ~CustomTypeDescriptorImpl()\ {\ Description::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::Create(nullptr))(Ptr), { L"proxy" }, vl::reflection::description::ValueInterfaceProxy::Create) #define END_INTERFACE_MEMBER(TYPENAME)\ if (GetBaseTypeDescriptorCount() == 0 && TDFlags == TypeDescriptorFlags::Interface) CLASS_MEMBER_BASE(IDescriptable)\ }\ };\ }; /*********************************************************************** Field ***********************************************************************/ #define CLASS_MEMBER_FIELD(FIELDNAME)\ AddProperty(\ new CustomFieldInfoImpl<\ ClassType,\ decltype(((ClassType*)0)->FIELDNAME)\ >(this, L ## #FIELDNAME, &ClassType::FIELDNAME)\ ); /*********************************************************************** Constructor ***********************************************************************/ #define NO_PARAMETER {L""} #define PROTECT_PARAMETERS(...) __VA_ARGS__ #define CLASS_MEMBER_CONSTRUCTOR(FUNCTIONTYPE, PARAMETERNAMES)\ {\ const wchar_t* parameterNames[]=PARAMETERNAMES;\ AddConstructor(new CustomConstructorInfoImpl(parameterNames));\ } #define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ {\ const wchar_t* parameterNames[]=PARAMETERNAMES;\ AddConstructor(\ new CustomStaticMethodInfoImpl(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ );\ } #define CLASS_MEMBER_EXTERNALCTOR(FUNCTIONTYPE, PARAMETERNAMES, SOURCE)\ CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PROTECT_PARAMETERS(PARAMETERNAMES), (FUNCTIONNAME_AddPointer)&::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")") /*********************************************************************** Method ***********************************************************************/ #define CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ {\ const wchar_t* parameterNames[]=PARAMETERNAMES;\ AddMethod(\ L ## #FUNCTIONNAME,\ new CustomExternalMethodInfoImpl<\ ClassType,\ vl::function_lambda::LambdaRetriveType::FunctionType\ >(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ );\ } #define CLASS_MEMBER_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\ CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($This, $Arguments)", L"::vl::Func<$Func>($This, &::" L ## #SOURCE L")") #define CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, INVOKETEMPLATE, CLOSURETEMPLATE)\ {\ const wchar_t* parameterNames[]=PARAMETERNAMES;\ auto methodInfo = new CustomMethodInfoImpl<\ ClassType,\ vl::function_lambda::LambdaRetriveType::FunctionType\ >\ (parameterNames, (FUNCTIONTYPE)&ClassType::FUNCTIONNAME, INVOKETEMPLATE, CLOSURETEMPLATE);\ AddMethod(\ L ## #EXPECTEDNAME,\ methodInfo\ );\ MethodPointerBinaryDataRetriver binaryDataRetriver(&ClassType::FUNCTIONNAME);\ MethodPointerBinaryDataRecorder::RecordMethod(binaryDataRetriver.GetBinaryData(), this, methodInfo);\ } #define CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\ CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, L"$This->" L ## #FUNCTIONNAME L"($Arguments)", L"::vl::Func<$Func>($This, &$Type::" L ## #FUNCTIONNAME L")") #define CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\ CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(FUNCTIONNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, nullptr, nullptr) #define CLASS_MEMBER_METHOD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES)\ CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME)) #define CLASS_MEMBER_METHOD(FUNCTIONNAME, PARAMETERNAMES)\ CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME)) /*********************************************************************** Static Method ***********************************************************************/ #define CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ {\ const wchar_t* parameterNames[]=PARAMETERNAMES;\ AddMethod(\ L ## #FUNCTIONNAME,\ new CustomStaticMethodInfoImpl<\ std::remove_pointer_t\ >(parameterNames, (FUNCTIONTYPE)SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\ );\ } #define CLASS_MEMBER_STATIC_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\ CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")") #define CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\ CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &ClassType::FUNCTIONNAME, nullptr, nullptr) #define CLASS_MEMBER_STATIC_METHOD(FUNCTIONNAME, PARAMETERNAMES)\ CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME)) /*********************************************************************** Event ***********************************************************************/ #define CLASS_MEMBER_EVENT(EVENTNAME)\ AddEvent(\ new CustomEventInfoImpl<\ ClassType,\ CustomEventFunctionTypeRetriver::Type\ >(this, L ## #EVENTNAME, &ClassType::EVENTNAME)\ ); /*********************************************************************** Property ***********************************************************************/ #define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\ AddProperty(\ new PropertyInfoImpl(\ this,\ L ## #PROPERTYNAME,\ dynamic_cast(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\ nullptr,\ nullptr\ )\ ); #define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\ AddProperty(\ new PropertyInfoImpl(\ this,\ L ## #PROPERTYNAME,\ dynamic_cast(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\ dynamic_cast(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\ nullptr\ )\ ); #define CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, GETTER, SETTER, EVENT)\ AddProperty(\ new PropertyInfoImpl(\ this,\ L ## #PROPERTYNAME,\ dynamic_cast(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\ dynamic_cast(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\ dynamic_cast(GetEventByName(L ## #EVENT, true))\ )\ ); #define CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, GETTER, EVENT)\ AddProperty(\ new PropertyInfoImpl(\ this,\ L ## #PROPERTYNAME,\ dynamic_cast(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\ nullptr,\ dynamic_cast(GetEventByName(L ## #EVENT, true))\ )\ ); #define CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE(PROPERTYNAME, GETTER, SETTER, REFERENCETEMPLATE)\ AddProperty(\ new PropertyInfoImpl_StaticCpp(\ this,\ L ## #PROPERTYNAME,\ dynamic_cast(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\ dynamic_cast(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 #define DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER(TYPENAME)\ template<>\ struct TypedValueSerializerProvider\ {\ static TYPENAME GetDefaultValue();\ static bool Serialize(const TYPENAME& input, WString& output);\ static bool Deserialize(const WString& input, TYPENAME& output);\ static IBoxedValue::CompareResult Compare(const TYPENAME& a, const TYPENAME& b);\ };\ REFLECTION_PREDEFINED_SERIALIZABLE_TYPES(DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER) #undef DEFINE_TYPED_VALUE_SERIALIZER_PROVIDER /*********************************************************************** Interface Implementation Proxy (Implement) ***********************************************************************/ #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA #pragma warning(push) #pragma warning(disable:4250) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerator) Value GetCurrent()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetCurrent); } vint GetIndex()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetIndex); } bool Next()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(Next); } END_INTERFACE_PROXY(IValueEnumerator) BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(IValueEnumerable) Ptr 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 GetKeys()override { INVOKEGET_INTERFACE_PROXY_NOPARAMS(GetKeys); } Ptr 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 ***********************************************************************/ /// Register all reflectable types in VlppReflection. /// Returns true if this operation succeeded. extern bool LoadPredefinedTypes(); } } } #endif