chore: experimentations
This commit is contained in:
133
Engine.Serialization/Converters/EntityConverter.cs
Normal file
133
Engine.Serialization/Converters/EntityConverter.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Factory;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Syntriax.Engine.Serialization;
|
||||
|
||||
public class EntityConverter(IReadOnlyDictionary<string, IEntity> entities) : IYamlTypeConverter
|
||||
{
|
||||
private readonly IReadOnlyDictionary<string, IEntity> Entities = entities;
|
||||
private readonly HashSet<IEntity> entitiesVisited = [];
|
||||
|
||||
public bool Accepts(Type type) => typeof(IEntity).IsAssignableFrom(type);
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
|
||||
{
|
||||
parser.Consume<MappingStart>();
|
||||
|
||||
TypeContainer typeContainer = (TypeContainer)rootDeserializer(typeof(TypeContainer))!;
|
||||
|
||||
object instance = TypeFactory.Get(typeContainer.Type);
|
||||
|
||||
while (!parser.TryConsume<MappingEnd>(out _))
|
||||
{
|
||||
string key = parser.Consume<Scalar>().Value;
|
||||
|
||||
if (type.GetField(key, BindingFlags.Instance | BindingFlags.NonPublic) is FieldInfo fieldInfo)
|
||||
{
|
||||
object? fieldValue = rootDeserializer(fieldInfo.FieldType);
|
||||
fieldInfo.SetValue(instance, fieldValue);
|
||||
}
|
||||
else if (type.GetProperty(key) is PropertyInfo propertyInfo)
|
||||
{
|
||||
object? propertyValue = rootDeserializer(propertyInfo.PropertyType);
|
||||
propertyInfo.SetValue(instance, propertyValue);
|
||||
}
|
||||
else
|
||||
parser.SkipThisAndNestedEvents();
|
||||
}
|
||||
|
||||
parser.TryConsume<MappingEnd>(out _);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
|
||||
{
|
||||
if (type.HasAttribute<IgnoreSerializationAttribute>())
|
||||
{
|
||||
emitter.Emit(new Scalar(""));
|
||||
return;
|
||||
}
|
||||
|
||||
IEntity entity = (IEntity)value!;
|
||||
if (!entitiesVisited.Add(entity))
|
||||
{
|
||||
emitter.Emit(new Scalar(entity.Id));
|
||||
return;
|
||||
}
|
||||
|
||||
emitter.Emit(new MappingStart());
|
||||
serializer(new TypeContainer(value), typeof(TypeContainer));
|
||||
|
||||
TypeData typeData = Utils.GetTypeData(type);
|
||||
|
||||
foreach (PropertyInfo propertyInfo in typeData.Properties)
|
||||
{
|
||||
if (propertyInfo.HasAttribute<IgnoreSerializationAttribute>())
|
||||
continue;
|
||||
|
||||
emitter.Emit(new Scalar(propertyInfo.Name));
|
||||
object? propertyValue = propertyInfo.GetValue(value);
|
||||
|
||||
EmitValue(propertyValue, propertyInfo.PropertyType, emitter, serializer);
|
||||
}
|
||||
|
||||
foreach (FieldInfo fieldInfo in typeData.Fields)
|
||||
{
|
||||
if (fieldInfo.HasAttribute<System.Runtime.CompilerServices.CompilerGeneratedAttribute>())
|
||||
continue;
|
||||
|
||||
if (fieldInfo.HasAttribute<IgnoreSerializationAttribute>())
|
||||
continue;
|
||||
|
||||
// if (!fieldInfo.HasAttribute<SerializeAttribute>())
|
||||
// continue;
|
||||
|
||||
emitter.Emit(new Scalar(fieldInfo.Name));
|
||||
object? fieldValue = fieldInfo.GetValue(value);
|
||||
|
||||
EmitValue(fieldValue, fieldInfo.FieldType, emitter, serializer);
|
||||
}
|
||||
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
|
||||
private static void EmitValue(object? value, Type declaredType, IEmitter emitter, ObjectSerializer serializer)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
emitter.Emit(new Scalar(""));
|
||||
return;
|
||||
}
|
||||
|
||||
if (value is IEntity entity)
|
||||
{
|
||||
emitter.Emit(new Scalar(entity.Id));
|
||||
return;
|
||||
}
|
||||
|
||||
bool isSequence = Utils.IsEnumerable(declaredType);
|
||||
|
||||
if (!isSequence)
|
||||
{
|
||||
serializer(value);
|
||||
return;
|
||||
}
|
||||
|
||||
IEnumerable sequence = (IEnumerable)value;
|
||||
|
||||
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
|
||||
foreach (object? item in sequence)
|
||||
if (value is IEntity sequenceEntity)
|
||||
emitter.Emit(new Scalar(sequenceEntity.Id));
|
||||
else
|
||||
serializer(item);
|
||||
emitter.Emit(new SequenceEnd());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user