Skip to content

Commit 47120ca

Browse files
committed
Feature: Add mechanism of centralizing all property get and set operation, to be able to operate on generic xml level. (collect class instances, class types, field names in same place)
1 parent 4a899cf commit 47120ca

8 files changed

Lines changed: 189 additions & 6 deletions

File tree

SolutionProjectModel/CppReflect.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,73 @@ bool FromXml( void* pclass, CppTypeInfo& type, const wchar_t* xml, CStringW& err
144144
return NodeToData( doc2.first_child(), pclass, type, error );
145145
}
146146

147+
148+
ReflectPath::ReflectPath(CppTypeInfo& type, const char* field)
149+
{
150+
// Doubt that class hierarchy is more complex than 5 levels, but increase this size if it's.
151+
types.reserve(5);
152+
fields.reserve(5);
153+
types.push_back(type);
154+
fields.push_back(field);
155+
}
156+
157+
void ReflectPath::Init(ReflectClass* instance)
158+
{
159+
instances.clear();
160+
instances.push_back(instance);
161+
types.resize(1);
162+
fields.resize(1);
163+
}
164+
165+
166+
//ReflectClass::ReflectClass() : _parent(nullptr)
167+
//{
168+
//}
169+
170+
ReflectClass::ReflectClass(ReflectClass* parent, const char* fieldName) : _parent(parent)
171+
{
172+
_fieldName = fieldName;
173+
}
174+
175+
ReflectClass::ReflectClass(const ReflectClass& clone) :
176+
_parent(clone._parent)
177+
{
178+
}
179+
180+
181+
void ReflectClass::OnBeforeGetProperty(ReflectPath& path)
182+
{
183+
if(!_parent)
184+
return;
185+
186+
// Anonymous fields can be skipped (Not intrested in their path)
187+
if (_fieldName.length() != 0)
188+
{
189+
path.types.push_back(GetType());
190+
path.fields.push_back(_fieldName.c_str());
191+
path.instances.push_back(this);
192+
}
193+
194+
_parent->OnBeforeGetProperty(path);
195+
}
196+
197+
void ReflectClass::OnAfterSetProperty(ReflectPath& path)
198+
{
199+
if (!_parent)
200+
return;
201+
202+
// Anonymous fields can be skipped (Not intrested in their path)
203+
if( _fieldName.length() != 0 )
204+
{
205+
path.types.push_back(GetType());
206+
path.fields.push_back(_fieldName.c_str());
207+
path.instances.push_back(this);
208+
}
209+
210+
_parent->OnAfterSetProperty(path);
211+
}
212+
213+
214+
215+
216+

SolutionProjectModel/CppReflect.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,83 @@ bool FromXml( T* pclass, const wchar_t* xml, CStringW& error )
106106
return FromXml(pclass, type, xml, error);
107107
}
108108

109+
class ReflectClass;
110+
111+
//
112+
// Path to highlight property set / get.
113+
//
114+
// instances collects <this> pointers converted to ReflectClass. Restore original pointer by calling instance[x]->ReflectGetInstance().
115+
// fields collects field names
116+
// types collects class Types.
117+
//
118+
class ReflectPath
119+
{
120+
public:
121+
ReflectPath(CppTypeInfo& type, const char* field);
122+
123+
void Init(ReflectClass* instance);
124+
125+
std::vector<ReflectClass*> instances;
126+
std::vector<const char*> fields;
127+
std::vector<CppTypeInfo> types;
128+
};
129+
130+
131+
//
132+
// All classes which use C++ reflection should inherit from this base class.
133+
//
134+
class ReflectClass
135+
{
136+
protected:
137+
// Parent class, nullptr if don't have parent class.
138+
ReflectClass* _parent;
139+
140+
// Field name under assignment.
141+
std::string _fieldName;
142+
143+
public:
144+
// Default constructor - this class does not have parent class.
145+
ReflectClass():
146+
ReflectClass(nullptr)
147+
{
148+
}
149+
150+
ReflectClass(ReflectClass* parent, const char* fieldName = "");
151+
ReflectClass(const ReflectClass& clone);
152+
153+
virtual CppTypeInfo& GetType() = 0;
154+
virtual void* ReflectGetInstance() = 0;
155+
156+
// By default set / get property rebroadcats event to parent class
157+
virtual void OnBeforeGetProperty(ReflectPath& path);
158+
virtual void OnAfterSetProperty(ReflectPath& path);
159+
160+
private:
161+
};
162+
163+
template <class T>
164+
class ReflectClassT : public ReflectClass
165+
{
166+
public:
167+
// Default constructor - this class does not have parent class.
168+
ReflectClassT() :
169+
ReflectClassT(nullptr)
170+
{
171+
}
172+
173+
ReflectClassT(ReflectClass* parent, const char* fieldName = "") :
174+
ReflectClass(parent, fieldName)
175+
{
176+
}
177+
178+
virtual CppTypeInfo& GetType()
179+
{
180+
return T::GetType();
181+
}
182+
183+
virtual void* ReflectGetInstance()
184+
{
185+
return (T*) this;
186+
}
187+
};
109188

SolutionProjectModel/MacroHelpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,18 @@
104104
public: \
105105
ARGTYPE(x) GET_PREFIXED ARGNAME_BRACKETED(x) () \
106106
{ \
107+
static ReflectPath path(GetType(), ARGNAME_AS_STRING(x)); \
108+
path.Init(this); \
109+
OnBeforeGetProperty(path); \
107110
return ARGNAME_UNDERSCORE(x); \
108111
} \
109112
\
110113
void SET_PREFIXED ARGNAME_BRACKETED(x) ( ARGTYPE(x) v ) \
111114
{ \
112115
ARGNAME_UNDERSCORE(x) = v; \
116+
static ReflectPath path(GetType(), ARGNAME_AS_STRING(x)); \
117+
path.Init(this); \
118+
OnAfterSetProperty(path); \
113119
} \
114120
\
115121
__declspec(property(get = GET_PREFIXED ARGNAME_BRACKETED(x), \

SolutionProjectModel/Project.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ using namespace filesystem;
1717
template class __declspec(dllexport) std::allocator<char>;
1818
template class __declspec(dllexport) std::basic_string<char, std::char_traits<char>, std::allocator<char> >;
1919

20+
void VCConfiguration::OnAfterSetProperty(ReflectPath& path)
21+
{
22+
23+
}
24+
25+
2026
Project::Project()
2127
{
2228
New();

SolutionProjectModel/Project.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,22 @@
77
#include <functional> //std::functional
88
#include <guiddef.h> //GUID
99

10-
class SPM_DLLEXPORT VCConfiguration
10+
class SPM_DLLEXPORT VCConfiguration: ReflectClassT<VCConfiguration>
1111
{
1212
public:
13+
VCConfiguration():
14+
_Linker(this, "Link")
15+
{
16+
}
17+
18+
VCConfiguration(const VCConfiguration& clone) :
19+
_Linker(this, "Link")
20+
{
21+
}
22+
23+
virtual void OnAfterSetProperty(ReflectPath& path);
24+
25+
1326
// Configuration name, for example L"Debug|x64"
1427
std::wstring ConfigurationPlatfom;
1528

SolutionProjectModel/ProjectFile.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66
// warning C4251: ... needs to have dll-interface to be used by clients of class ...
77
#pragma warning( disable: 4251 )
8-
// warning C4275: non dll-interface class 'pugi::xml_document' used as base for dll-interface class 'Solution'
9-
#pragma warning( disable: 4275 )
10-
118

129
//
1310
// Information about that particular file.

SolutionProjectModel/ProjectFileTypes.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,27 @@ DECLARE_ENUM(ESubSystem, "subsystem_",
128128
);
129129

130130

131-
class SPM_DLLEXPORT LinkerSystemConf
131+
class SPM_DLLEXPORT LinkerSystemConf: ReflectClassT<LinkerSystemConf>
132132
{
133133
public:
134+
LinkerSystemConf(ReflectClass* parent) : ReflectClassT<LinkerSystemConf>(parent)
135+
{
136+
}
137+
134138
REFLECTABLE(LinkerSystemConf,
135139
(ESubSystem)SubSystem
136140
);
137141
};
138142

139143

140-
class SPM_DLLEXPORT LinkerConf
144+
class SPM_DLLEXPORT LinkerConf: ReflectClassT<LinkerConf>
141145
{
142146
public:
147+
LinkerConf(ReflectClass* parent, const char* field):
148+
ReflectClassT<LinkerConf>(parent, field), _System(this)
149+
{
150+
}
151+
143152
REFLECTABLE(LinkerConf,
144153
(LinkerSystemConf)System
145154
);

SolutionProjectModel/pch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@
1111
#include <guiddef.h>
1212
#include <functional>
1313

14+
// warning C4275: non dll-interface class 'pugi::xml_document' used as base for dll-interface class 'Solution'
15+
#pragma warning( disable: 4275 )
16+

0 commit comments

Comments
 (0)