Implemented deserialization of lists

This commit is contained in:
Kah Wei 2022-11-13 02:42:47 +08:00
parent 889d3dac4c
commit d98deda63d
5 changed files with 172 additions and 88 deletions

View File

@ -41,7 +41,12 @@ namespace SHADE
bool ReflectionUtilities::FieldIsList(System::Reflection::FieldInfo^ fieldInfo)
{
return fieldInfo->FieldType->IsGenericType
&& fieldInfo->FieldType->GetGenericTypeDefinition() == System::Collections::Generic::List<int>::typeid->GetGenericTypeDefinition();
return IsList(fieldInfo->FieldType);
}
bool ReflectionUtilities::IsList(System::Type^ type)
{
return type->IsGenericType
&& type->GetGenericTypeDefinition() == System::Collections::Generic::List<int>::typeid->GetGenericTypeDefinition();
}
}

View File

@ -45,5 +45,11 @@ namespace SHADE
/// <param name="fieldInfo">The field to check.</param>
/// <returns>True if fieldInfo is describing a generic List.</returns>
static bool FieldIsList(System::Reflection::FieldInfo^ fieldInfo);
/// <summary>
/// Checks if the specified type is a generic List type.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>True if type is a generic List.</returns>
static bool IsList(System::Type^ type);
};
}

View File

@ -174,78 +174,87 @@ namespace SHADE
return INSERTED;
}
void SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
/*---------------------------------------------------------------------------------*/
/* Deserialization Helper Functions */
/*---------------------------------------------------------------------------------*/
bool SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
if (fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||
fieldAssignYaml<System::UInt16>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt32>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt64>(fieldInfo, object, node) ||
fieldAssignYaml<System::Byte> (fieldInfo, object, node) ||
fieldAssignYaml<bool> (fieldInfo, object, node) ||
fieldAssignYaml<float> (fieldInfo, object, node) ||
fieldAssignYaml<double> (fieldInfo, object, node))
const bool ASSIGNED =
fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||
fieldAssignYaml<System::UInt16>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt32>(fieldInfo, object, node) ||
fieldAssignYaml<System::UInt64>(fieldInfo, object, node) ||
fieldAssignYaml<System::Byte> (fieldInfo, object, node) ||
fieldAssignYaml<bool> (fieldInfo, object, node) ||
fieldAssignYaml<float> (fieldInfo, object, node) ||
fieldAssignYaml<double> (fieldInfo, object, node) ||
fieldAssignYaml<System::Enum> (fieldInfo, object, node) ||
fieldAssignYaml<System::String>(fieldInfo, object, node) ||
fieldAssignYaml<Vector2> (fieldInfo, object, node) ||
fieldAssignYaml<Vector3> (fieldInfo, object, node) ||
fieldAssignYaml<GameObject> (fieldInfo, object, node);
if (!ASSIGNED)
{
return;
}
else if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid))
{
fieldInfo->SetValue(object, node.as<int>());
}
else if (fieldInfo->FieldType == System::String::typeid)
{
fieldInfo->SetValue(object, Convert::ToCLI(node.as<std::string>()));
}
else if (fieldInfo->FieldType == Vector2::typeid)
{
if (node.IsSequence() && node.size() == 2)
if (ReflectionUtilities::FieldIsList(fieldInfo))
{
Vector2 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
fieldInfo->SetValue(object, vec);
}
else
{
Debug::LogWarning
(
System::String::Format("[SerialisationUtilities] Invalid YAML Node provided for deserialization of a Vector2 \"{0}\" field in \"{1}\" script.",
fieldInfo->Name, object->GetType()->FullName)
);
System::Type^ elemType = fieldInfo->FieldType->GenericTypeArguments[0];
System::Collections::IList^ iList = safe_cast<System::Collections::IList^>(fieldInfo->GetValue(object));
if (node.IsSequence())
{
// Get list size
const int LIST_SIZE = static_cast<int>(node.size());
if (LIST_SIZE > 0)
{
// Get list type
array<System::Type^>^ typeList = gcnew array<System::Type^>{ elemType };
System::Type^ listType = System::Collections::Generic::List<int>::typeid->GetGenericTypeDefinition()->MakeGenericType(typeList);
// Create a list of the specified type
array<int>^ params = gcnew array<int>{ node.size() };
object = System::Activator::CreateInstance(listType, params);
System::Collections::IList^ list = safe_cast<System::Collections::IList^>(object);
// Populate the list
for (int i = 0; i < LIST_SIZE; ++i)
{
// Create the object
System::Object^ obj = System::Activator::CreateInstance(elemType);
// Set it's value
if (varAssignYaml(obj, node[i]))
{
list->Add(obj);
}
}
}
}
return true;
}
}
else if (fieldInfo->FieldType == Vector3::typeid)
{
if (node.IsSequence() && node.size() == 3)
{
Vector3 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
vec.z = node[2].as<float>();
fieldInfo->SetValue(object, vec);
}
else
{
Debug::LogWarning
(
System::String::Format("[SerialisationUtilities] Invalid YAML Node provided for deserialization of a Vector3 \"{0}\" field in \"{1}\" script.",
fieldInfo->Name, object->GetType()->FullName)
);
}
}
else if (fieldInfo->FieldType == GameObject::typeid)
{
const uint32_t EID = node.as<uint32_t>();
fieldInfo->SetValue(object, EID == MAX_EID ? GameObject() : GameObject(EID));
}
else // Not any of the supported types
{
Debug::LogWarning(Convert::ToNative(System::String::Format
(
"[SerialisationUtilities] Failed to parse \"{0}\" of \"{1}\" type for deserialisation.",
fieldInfo->Name, fieldInfo->FieldType)
));
}
return ASSIGNED;
}
bool SerialisationUtilities::varAssignYaml(System::Object^% object, YAML::Node& node)
{
const bool DESERIALISED =
varAssignYamlInternal<System::Int16> (object, node) ||
varAssignYamlInternal<System::Int32> (object, node) ||
varAssignYamlInternal<System::Int64> (object, node) ||
varAssignYamlInternal<System::UInt16>(object, node) ||
varAssignYamlInternal<System::UInt32>(object, node) ||
varAssignYamlInternal<System::UInt64>(object, node) ||
varAssignYamlInternal<System::Byte> (object, node) ||
varAssignYamlInternal<bool> (object, node) ||
varAssignYamlInternal<float> (object, node) ||
varAssignYamlInternal<double> (object, node) ||
varAssignYamlInternal<System::Enum> (object, node) ||
varAssignYamlInternal<System::String>(object, node) ||
varAssignYamlInternal<Vector2> (object, node) ||
varAssignYamlInternal<Vector3> (object, node) ||
varAssignYamlInternal<GameObject> (object, node);
return DESERIALISED;
}
}

View File

@ -36,7 +36,6 @@ namespace SHADE
{
if constexpr (std::is_same_v<FieldType, System::Enum>)
{
Debug::Log("Enum Specialization");
if (object->GetType()->IsSubclassOf(System::Enum::typeid))
{
fieldNode = std::to_string(safe_cast<int>(object));
@ -45,7 +44,6 @@ namespace SHADE
}
else if constexpr (std::is_same_v<FieldType, System::String>)
{
Debug::Log("String Specialization");
if (object->GetType() == System::String::typeid)
{
System::String^ str = safe_cast<System::String^>(object);
@ -55,7 +53,6 @@ namespace SHADE
}
else if constexpr (std::is_same_v<FieldType, Vector2>)
{
Debug::Log("Vec2 Specialization");
if (object->GetType() == Vector2::typeid)
{
Vector2 vec = safe_cast<Vector2>(object);
@ -67,7 +64,6 @@ namespace SHADE
}
else if constexpr (std::is_same_v<FieldType, Vector3>)
{
Debug::Log("Vec3 Specialization");
if (object->GetType() == Vector3::typeid)
{
Vector3 vec = safe_cast<Vector3>(object);
@ -80,7 +76,6 @@ namespace SHADE
}
else if constexpr (std::is_same_v<FieldType, GameObject>)
{
Debug::Log("GameObject Specialization");
if (object->GetType() == GameObject::typeid)
{
GameObject gameObj = safe_cast<GameObject>(object);
@ -90,7 +85,6 @@ namespace SHADE
}
else
{
Debug::Log("No Specialization");
if (object->GetType() == FieldType::typeid)
{
FieldType value = safe_cast<FieldType>(object);
@ -108,18 +102,87 @@ namespace SHADE
template<typename FieldType>
bool SerialisationUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
return fieldAssignYaml<FieldType, ToNativeType_T<FieldType>>(fieldInfo, object, node);
}
template<typename FieldType, typename CastType>
bool SerialisationUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
if (fieldInfo->FieldType == FieldType::typeid)
System::Object^ valueObj = fieldInfo->GetValue(object);
if (varAssignYamlInternal<FieldType>(valueObj, node))
{
fieldInfo->SetValue(object, node.as<CastType>());
fieldInfo->SetValue(object, valueObj);
return true;
}
return false;
}
template<typename FieldType, typename CastType>
bool SerialisationUtilities::varAssignYamlInternal(System::Object^% object, YAML::Node& node)
{
if constexpr (std::is_same_v<FieldType, System::Enum>)
{
if (object->GetType()->IsSubclassOf(System::Enum::typeid))
{
object = node.as<int>();
return true;
}
}
else if constexpr (std::is_same_v<FieldType, System::Collections::IList>)
{
if (ReflectionUtilities::FieldIsList(fieldInfo))
{
System::Collections::IList^ iList = safe_cast<System::Collections::IList^>(object);
object = gcnew
if (node.IsSequence() )
}
}
else
{
if (object->GetType() == FieldType::typeid)
{
if constexpr (std::is_same_v<FieldType, System::String>)
{
object = Convert::ToCLI(node.as<std::string>());
}
else if constexpr (std::is_same_v<FieldType, Vector2>)
{
if (node.IsSequence() && node.size() == 2)
{
Vector2 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
object = vec;
}
else
{
return false;
}
}
else if constexpr (std::is_same_v<FieldType, Vector3>)
{
if (node.IsSequence() && node.size() == 3)
{
Vector3 vec;
vec.x = node[0].as<float>();
vec.y = node[1].as<float>();
vec.z = node[2].as<float>();
object = vec;
}
else
{
return false;
}
}
else if constexpr (std::is_same_v<FieldType, GameObject>)
{
const uint32_t EID = node.as<uint32_t>();
object = (EID == MAX_EID ? GameObject() : GameObject(EID));
}
else
{
object = node.as<CastType>();
}
return true;
}
}
return false;
}
}

View File

@ -63,11 +63,12 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Deserialization Helper Functions */
/*-----------------------------------------------------------------------------*/
static void writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
static bool writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
template<typename FieldType>
static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
template<typename FieldType, typename CastType>
static bool fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node);
static bool varAssignYaml(System::Object^% object, YAML::Node& node);
template<typename FieldType, typename CastType = ToNativeType_T<FieldType>>
static bool varAssignYamlInternal(System::Object^% object, YAML::Node& node);
};
}