Files
beyond/Assets/ThirdParty/FullSerializer/Source/Converters/fsReflectedConverter.cs
2024-11-20 15:21:28 +01:00

95 lines
3.7 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(/*throwException:*/ false);
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(/*throwException:*/ false);
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();
}
}
}