#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#define VCZH_REFLECTION_GUITYPEDESCRIPTORMACROS
#include "GuiTypeDescriptorBuilder.h"
#include "GuiTypeDescriptorBuilder_Container.h"
#include "GuiTypeDescriptorBuilder_Function.h"
#include "GuiTypeDescriptorBuilder_Struct.h"
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
namespace
{
namespace
{
namespace
{
template
<
typename
>
struct
CustomTypeDescriptorSelector
{};
struct
{
typedef
collections
::
<
,
*>
;
class
:
public
virtual
{
public
:
virtual
void
(
const
&
,
*
) =
0
;
virtual
*
(
const
&
) =
0
;
};
[
4
];
static
inline
(
const
&
,
const
&
)
{
{
auto
=
.
[
0
] -
.
[
0
];
if
(
result
!=
0
)
return
result
;
}
{
auto
=
.
[
1
] -
.
[
1
];
if
(
result
!=
0
)
return
result
;
}
{
auto
=
.
[
2
] -
.
[
2
];
if
(
result
!=
0
)
return
result
;
}
{
auto
=
.
[
3
] -
.
[
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(<)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) <
0
; }
COMPARE(<=)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) <=
0
; }
COMPARE(>)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) >
0
; }
COMPARE(>=)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) >=
0
; }
COMPARE(==)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) ==
0
; }
COMPARE(!=)
inline
bool
(
const
&
)
const
{
return
(*
this
,
) !=
0
; }
#undef COMPARE
};
template
<
typename
>
union
MethodPointerBinaryDataRetriver
{
;
;
MethodPointerBinaryDataRetriver
(
)
{
(&
,
0
,
sizeof
(
));
=
;
}
const
&
()
{
static_assert
(
sizeof
(
) <=
sizeof
(
),
"Your C++ compiler is bad!"
);
return
;
}
};
template
<
typename
,
>
struct
MethodPointerBinaryDataRecorder
{
static
void
(
const
&
,
*
,
*
)
{
}
};
template
<
typename
>
struct
MethodPointerBinaryDataRecorder
<
,
::
>
{
static
void
(
const
&
,
*
,
*
)
{
auto
=
dynamic_cast
<
::
*>(
);
CHECK_ERROR(impl != nullptr, L"Internal error: RecordMethod can only be called when registering methods.");
do
{
if
(!(
impl
!=
nullptr
))
throw
(
L"Internal error: RecordMethod can only be called when registering methods."
);}
while
(
0
);
impl
->
(
,
);
}
};
template
<
typename
>
using
=
*;
#define BEGIN_TYPE_INFO_NAMESPACE namespace vl{namespace reflection{namespace description{
#define END_TYPE_INFO_NAMESPACE }}}
#define ADD_TYPE_INFO(TYPENAME)\
{\
Ptr<ITypeDescriptor> type=new CustomTypeDescriptorSelector<TYPENAME>::CustomTypeDescriptorImpl();\
manager->SetTypeDescriptor(TypeInfo<TYPENAME>::content.typeName, type);\
}
#define INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
static INTERFACE* Create(Ptr<IValueInterfaceProxy> proxy)\
{\
auto obj = new ValueInterfaceProxy<INTERFACE>();\
obj->SetProxy(proxy);\
return obj;\
}\
#define INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
static Ptr<INTERFACE> Create(Ptr<IValueInterfaceProxy> proxy)\
{\
auto obj = new ValueInterfaceProxy<INTERFACE>();\
obj->SetProxy(proxy);\
return obj;\
}\
#define BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
template<>\
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE>\
{\
typedef INTERFACE _interface_proxy_InterfaceType;\
public:\
#define BEGIN_INTERFACE_PROXY_NOPARENT_RAWPTR(INTERFACE)\
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_NOPARENT_SHAREDPTR(INTERFACE)\
BEGIN_INTERFACE_PROXY_NOPARENT_HEADER(INTERFACE)\
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, ...)\
template<>\
class ValueInterfaceProxy<INTERFACE> : public ValueInterfaceImpl<INTERFACE, __VA_ARGS__>\
{\
typedef INTERFACE _interface_proxy_InterfaceType;\
public:\
#define BEGIN_INTERFACE_PROXY_RAWPTR(INTERFACE, ...)\
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
INTERFACE_PROXY_CTOR_RAWPTR(INTERFACE)\
#define BEGIN_INTERFACE_PROXY_SHAREDPTR(INTERFACE, ...)\
BEGIN_INTERFACE_PROXY_HEADER(INTERFACE, __VA_ARGS__)\
INTERFACE_PROXY_CTOR_SHAREDPTR(INTERFACE)\
#define END_INTERFACE_PROXY(INTERFACE)\
};
template
<
typename
,
typename
,
typename
...
>
auto
(
...)->
(
::*)(
...)
{
return
nullptr
;
}
#define PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
static ITypeDescriptor* _interface_proxy_typeDescriptor = nullptr;\
static IMethodInfo* _interface_proxy_methodInfo = nullptr;\
if (_interface_proxy_typeDescriptor != static_cast<DescriptableObject*>(this)->GetTypeDescriptor())\
{\
_interface_proxy_typeDescriptor = static_cast<DescriptableObject*>(this)->GetTypeDescriptor();\
CHECK_ERROR(_interface_proxy_typeDescriptor != nullptr, L"Internal error: The type of this interface has not been registered.");\
auto impl = dynamic_cast<MethodPointerBinaryData::IIndexer*>(_interface_proxy_typeDescriptor);\
CHECK_ERROR(impl != nullptr, L"Internal error: BEGIN_INTERFACE_PROXY is the only correct way to register an interface with a proxy.");\
auto _interface_proxy_method\
= (decltype(MethodTypeTrait<_interface_proxy_InterfaceType, decltype(METHODNAME(__VA_ARGS__))>(__VA_ARGS__)))\
&_interface_proxy_InterfaceType::METHODNAME;\
MethodPointerBinaryDataRetriver<decltype(_interface_proxy_method)> binaryData(_interface_proxy_method);\
_interface_proxy_methodInfo = impl->GetIndexedMethodInfo(binaryData.GetBinaryData());\
}\
#define INVOKE_INTERFACE_PROXY(METHODNAME, ...)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__))))
#define INVOKE_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create())
#define INVOKEGET_INTERFACE_PROXY(METHODNAME, ...)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME, __VA_ARGS__)\
return UnboxValue<decltype(METHODNAME(__VA_ARGS__))>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create(collections::From((collections::Array<Value>&)(Value_xs(), __VA_ARGS__)))))
#define INVOKEGET_INTERFACE_PROXY_NOPARAMS(METHODNAME)\
PREPARE_INVOKE_INTERFACE_PROXY(METHODNAME)\
return UnboxValue<decltype(METHODNAME())>(proxy->Invoke(_interface_proxy_methodInfo, IValueList::Create()))
#define BEGIN_ENUM_ITEM_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public EnumTypeDescriptor<TYPENAME, TDFLAGS>\
{\
typedef TYPENAME EnumType;\
public:\
void LoadInternal()override\
{\
EnumTypeDescriptor<TYPENAME, TDFLAGS>::LoadInternal();\
#define BEGIN_ENUM_ITEM(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::NormalEnum)
#define BEGIN_ENUM_ITEM_MERGABLE(TYPENAME) BEGIN_ENUM_ITEM_FLAG(TYPENAME, TypeDescriptorFlags::FlagEnum)
#define END_ENUM_ITEM(TYPENAME)\
}\
};\
};
#define ENUM_ITEM_NAMESPACE(TYPENAME) typedef TYPENAME EnumItemNamespace;
#define ENUM_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, ITEMNAME);
#define ENUM_NAMESPACE_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumItemNamespace::ITEMNAME);
#define ENUM_CLASS_ITEM(ITEMNAME) enumType->AddItem(L ## #ITEMNAME, EnumType::ITEMNAME);
#define BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public StructTypeDescriptor<TYPENAME, TDFLAGS>\
{\
typedef TYPENAME StructType;\
protected:\
void LoadInternal()override\
{
#define BEGIN_STRUCT_MEMBER(TYPENAME)\
BEGIN_STRUCT_MEMBER_FLAG(TYPENAME, TypeDescriptorFlags::Struct)
#define END_STRUCT_MEMBER(TYPENAME)\
}\
};\
};
#define STRUCT_MEMBER(FIELDNAME)\
fields.Add(L ## #FIELDNAME, new StructFieldInfo<decltype(((StructType*)0)->FIELDNAME)>(this, &StructType::FIELDNAME, L ## #FIELDNAME));
#define BEGIN_CLASS_MEMBER(TYPENAME)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public TypeDescriptorImpl\
{\
typedef TYPENAME ClassType;\
static const TypeDescriptorFlags TDFlags = TypeDescriptorFlags::Class;\
public:\
CustomTypeDescriptorImpl()\
:TypeDescriptorImpl(TDFlags, &TypeInfo<TYPENAME>::content)\
{\
Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
}\
~CustomTypeDescriptorImpl()\
{\
Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
}\
protected:\
bool IsAggregatable()override\
{\
return AcceptValue<typename PointerConvertable<TYPENAME, AggregatableDescription<TYPENAME>>::YesNoType>::Result;\
}\
void LoadInternal()override\
{
#define CLASS_MEMBER_BASE(TYPENAME)\
AddBaseType(description::GetTypeDescriptor<TYPENAME>());
#define END_CLASS_MEMBER(TYPENAME)\
if (GetBaseTypeDescriptorCount() == 0) CLASS_MEMBER_BASE(DescriptableObject)\
}\
};\
};
#define BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TDFLAGS)\
template<>\
struct CustomTypeDescriptorSelector<TYPENAME>\
{\
public:\
class CustomTypeDescriptorImpl : public TypeDescriptorImpl, public MethodPointerBinaryData::IIndexer\
{\
typedef TYPENAME ClassType;\
static const TypeDescriptorFlags TDFlags = TDFLAGS;\
MethodPointerBinaryData::MethodMap methodsForProxy;\
public:\
CustomTypeDescriptorImpl()\
:TypeDescriptorImpl(TDFLAGS, &TypeInfo<TYPENAME>::content)\
{\
Description<TYPENAME>::SetAssociatedTypeDescriptor(this);\
}\
~CustomTypeDescriptorImpl()\
{\
Description<TYPENAME>::SetAssociatedTypeDescriptor(0);\
}\
void IndexMethodInfo(const MethodPointerBinaryData& data, IMethodInfo* methodInfo)override\
{\
methodsForProxy.Add(data, methodInfo);\
}\
IMethodInfo* GetIndexedMethodInfo(const MethodPointerBinaryData& data)override\
{\
Load();\
return methodsForProxy[data];\
}\
protected:\
void LoadInternal()override\
{
#define BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
BEGIN_INTERFACE_MEMBER_NOPROXY_FLAG(TYPENAME, TypeDescriptorFlags::Interface)
#define BEGIN_INTERFACE_MEMBER(TYPENAME)\
BEGIN_INTERFACE_MEMBER_NOPROXY(TYPENAME)\
CLASS_MEMBER_EXTERNALCTOR(decltype(ValueInterfaceProxy<TYPENAME>::Create(nullptr))(Ptr<IValueInterfaceProxy>), { L"proxy" }, vl::reflection::description::ValueInterfaceProxy<TYPENAME>::Create)
#define END_INTERFACE_MEMBER(TYPENAME)\
if (GetBaseTypeDescriptorCount() == 0 && TDFlags == TypeDescriptorFlags::Interface) CLASS_MEMBER_BASE(IDescriptable)\
}\
};\
};
#define CLASS_MEMBER_FIELD(FIELDNAME)\
AddProperty(\
new CustomFieldInfoImpl<\
ClassType,\
decltype(((ClassType*)0)->FIELDNAME)\
>(this, L ## #FIELDNAME, &ClassType::FIELDNAME)\
);
#define NO_PARAMETER {L""}
#define PROTECT_PARAMETERS(...) __VA_ARGS__
#define CLASS_MEMBER_CONSTRUCTOR(FUNCTIONTYPE, PARAMETERNAMES)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddConstructor(new CustomConstructorInfoImpl<FUNCTIONTYPE>(parameterNames));\
}
#define CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PARAMETERNAMES, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddConstructor(\
new CustomStaticMethodInfoImpl<FUNCTIONTYPE>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_EXTERNALCTOR(FUNCTIONTYPE, PARAMETERNAMES, SOURCE)\
CLASS_MEMBER_EXTERNALCTOR_TEMPLATE(FUNCTIONTYPE, PROTECT_PARAMETERS(PARAMETERNAMES), (FUNCTIONNAME_AddPointer<FUNCTIONTYPE>)&::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
#define CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddMethod(\
L ## #FUNCTIONNAME,\
new CustomExternalMethodInfoImpl<\
ClassType,\
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
>(parameterNames, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
CLASS_MEMBER_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($This, $Arguments)", L"::vl::Func<$Func>($This, &::" L ## #SOURCE L")")
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
auto methodInfo = new CustomMethodInfoImpl<\
ClassType,\
vl::function_lambda::LambdaRetriveType<FUNCTIONTYPE>::FunctionType\
>\
(parameterNames, (FUNCTIONTYPE)&ClassType::FUNCTIONNAME, INVOKETEMPLATE, CLOSURETEMPLATE);\
AddMethod(\
L ## #EXPECTEDNAME,\
methodInfo\
);\
MethodPointerBinaryDataRetriver<FUNCTIONTYPE> binaryDataRetriver(&ClassType::FUNCTIONNAME);\
MethodPointerBinaryDataRecorder<ClassType, TDFlags>::RecordMethod(binaryDataRetriver.GetBinaryData(), this, methodInfo);\
}
#define CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, L"$This->" L ## #FUNCTIONNAME L"($Arguments)", L"::vl::Func<$Func>($This, &$Type::" L ## #FUNCTIONNAME L")")
#define CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME_TEMPLATE(FUNCTIONNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, nullptr, nullptr)
#define CLASS_MEMBER_METHOD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_METHOD_OVERLOAD_RENAME(EXPECTEDNAME, FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
#define CLASS_MEMBER_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
{\
const wchar_t* parameterNames[]=PARAMETERNAMES;\
AddMethod(\
L ## #FUNCTIONNAME,\
new CustomStaticMethodInfoImpl<\
vl::function_lambda::FunctionObjectRetriveType<FUNCTIONTYPE>::FunctionType\
>(parameterNames, (FUNCTIONTYPE)SOURCE, INVOKETEMPLATE, CLOSURETEMPLATE)\
);\
}
#define CLASS_MEMBER_STATIC_EXTERNALMETHOD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE, SOURCE)\
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &::SOURCE, L"::" L ## #SOURCE L"($Arguments)", L"::vl::Func<$Func>(&::" L ## #SOURCE L")")
#define CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PARAMETERNAMES, FUNCTIONTYPE)\
CLASS_MEMBER_STATIC_EXTERNALMETHOD_TEMPLATE(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), FUNCTIONTYPE, &ClassType::FUNCTIONNAME, nullptr, nullptr)
#define CLASS_MEMBER_STATIC_METHOD(FUNCTIONNAME, PARAMETERNAMES)\
CLASS_MEMBER_STATIC_METHOD_OVERLOAD(FUNCTIONNAME, PROTECT_PARAMETERS(PARAMETERNAMES), decltype(&ClassType::FUNCTIONNAME))
#define CLASS_MEMBER_EVENT(EVENTNAME)\
AddEvent(\
new CustomEventInfoImpl<\
ClassType,\
CustomEventFunctionTypeRetriver<decltype(&ClassType::EVENTNAME)>::Type\
>(this, L ## #EVENTNAME, &ClassType::EVENTNAME)\
);
#define CLASS_MEMBER_PROPERTY_READONLY(PROPERTYNAME, GETTER)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
nullptr,\
nullptr\
)\
);
#define CLASS_MEMBER_PROPERTY(PROPERTYNAME, GETTER, SETTER)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
nullptr\
)\
);
#define CLASS_MEMBER_PROPERTY_EVENT(PROPERTYNAME, GETTER, SETTER, EVENT)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
)\
);
#define CLASS_MEMBER_PROPERTY_EVENT_READONLY(PROPERTYNAME, GETTER, EVENT)\
AddProperty(\
new PropertyInfoImpl(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
nullptr,\
dynamic_cast<EventInfoImpl*>(GetEventByName(L ## #EVENT, true))\
)\
);
#define CLASS_MEMBER_PROPERTY_REFERENCETEMPLATE(PROPERTYNAME, GETTER, SETTER, REFERENCETEMPLATE)\
AddProperty(\
new PropertyInfoImpl_StaticCpp(\
this,\
L ## #PROPERTYNAME,\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #GETTER, true)->GetMethod(0)),\
dynamic_cast<MethodInfoImpl*>(GetMethodGroupByName(L ## #SETTER, true)->GetMethod(0)),\
nullptr,\
WString(REFERENCETEMPLATE, false)\
)\
);
#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