pixelgon/Assets/Source/Converters/fsReflectedConverter.cs
2020-06-05 11:54:36 -07:00

93 lines
No EOL
3.6 KiB
C#

using System;
using System.Collections;
#if !UNITY_EDITOR && UNITY_WSA
// For System.Reflection.TypeExtensions
using System.Reflection;
#endif
namespace FullSerializer.Internal {
public class fsReflectedConverter : fsConverter {
public override bool CanProcess(Type type) {
if (type.Resolve().IsArray ||
typeof(ICollection).IsAssignableFrom(type)) {
return false;
}
return true;
}
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
serialized = fsData.CreateDictionary();
var result = fsResult.Success;
fsMetaType metaType = fsMetaType.Get(Serializer.Config, instance.GetType());
metaType.EmitAotData();
for (int i = 0; i < metaType.Properties.Length; ++i) {
fsMetaProperty property = metaType.Properties[i];
if (property.CanRead == false) continue;
fsData serializedData;
var itemResult = Serializer.TrySerialize(property.StorageType, property.OverrideConverterType,
property.Read(instance), out serializedData);
result.AddMessages(itemResult);
if (itemResult.Failed) {
continue;
}
serialized.AsDictionary[property.JsonName] = serializedData;
}
return result;
}
public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
var result = fsResult.Success;
// Verify that we actually have an Object
if ((result += CheckType(data, fsDataType.Object)).Failed) {
return result;
}
fsMetaType metaType = fsMetaType.Get(Serializer.Config, storageType);
metaType.EmitAotData();
for (int i = 0; i < metaType.Properties.Length; ++i) {
fsMetaProperty property = metaType.Properties[i];
if (property.CanWrite == false) continue;
fsData propertyData;
if (data.AsDictionary.TryGetValue(property.JsonName, out propertyData)) {
object deserializedValue = null;
// We have to read in the existing value, since we need to support partial
// deserialization. However, this is bad for perf.
// TODO: Find a way to avoid this call when we are not doing a partial deserialization
// Maybe through a new property, ie, Serializer.IsPartialSerialization, which just
// gets set when starting a new serialization? We cannot pipe the information
// through CreateInstance unfortunately.
if (property.CanRead) {
deserializedValue = property.Read(instance);
}
var itemResult = Serializer.TryDeserialize(propertyData, property.StorageType,
property.OverrideConverterType, ref deserializedValue);
result.AddMessages(itemResult);
if (itemResult.Failed) continue;
property.Write(instance, deserializedValue);
}
}
return result;
}
public override object CreateInstance(fsData data, Type storageType) {
fsMetaType metaType = fsMetaType.Get(Serializer.Config, storageType);
return metaType.CreateInstance();
}
}
}