chore: experimentations

This commit is contained in:
Syntriax 2025-04-23 23:20:00 +03:00
parent 2637f99456
commit 35a75d993b
5 changed files with 55 additions and 33 deletions

View File

@ -1,6 +1,6 @@
using System.Collections;
using System.Reflection;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Factory;
using YamlDotNet.Core;
@ -9,17 +9,15 @@ using YamlDotNet.Serialization;
namespace Syntriax.Engine.Serialization;
public class InstanceConverter : IEngineTypeYamlConverter
public class EntityConverter(IReadOnlyDictionary<string, IEntity> entities) : IYamlTypeConverter
{
private int depth = 0;
private int maxDepth = 5;
private readonly IReadOnlyDictionary<string, IEntity> Entities = entities;
private readonly HashSet<IEntity> entitiesVisited = [];
public bool Accepts(Type type) => !type.IsPrimitive && type != typeof(string);
public bool Accepts(Type type) => typeof(IEntity).IsAssignableFrom(type);
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
{
if (depth > maxDepth)
return null;
parser.Consume<MappingStart>();
TypeContainer typeContainer = (TypeContainer)rootDeserializer(typeof(TypeContainer))!;
@ -32,16 +30,12 @@ public class InstanceConverter : IEngineTypeYamlConverter
if (type.GetField(key, BindingFlags.Instance | BindingFlags.NonPublic) is FieldInfo fieldInfo)
{
depth++;
object? fieldValue = rootDeserializer(fieldInfo.FieldType);
depth--;
fieldInfo.SetValue(instance, fieldValue);
}
else if (type.GetProperty(key) is PropertyInfo propertyInfo)
{
depth++;
object? propertyValue = rootDeserializer(propertyInfo.PropertyType);
depth--;
propertyInfo.SetValue(instance, propertyValue);
}
else
@ -55,6 +49,19 @@ public class InstanceConverter : IEngineTypeYamlConverter
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));
@ -68,12 +75,7 @@ public class InstanceConverter : IEngineTypeYamlConverter
emitter.Emit(new Scalar(propertyInfo.Name));
object? propertyValue = propertyInfo.GetValue(value);
depth++;
if (depth <= maxDepth)
EmitValue(propertyValue, propertyInfo.PropertyType, emitter, serializer);
else
emitter.Emit(new Scalar("Skipped"));
depth--;
EmitValue(propertyValue, propertyInfo.PropertyType, emitter, serializer);
}
foreach (FieldInfo fieldInfo in typeData.Fields)
@ -81,18 +83,16 @@ public class InstanceConverter : IEngineTypeYamlConverter
if (fieldInfo.HasAttribute<System.Runtime.CompilerServices.CompilerGeneratedAttribute>())
continue;
if (!fieldInfo.HasAttribute<SerializeAttribute>())
if (fieldInfo.HasAttribute<IgnoreSerializationAttribute>())
continue;
// if (!fieldInfo.HasAttribute<SerializeAttribute>())
// continue;
emitter.Emit(new Scalar(fieldInfo.Name));
object? fieldValue = fieldInfo.GetValue(value);
depth++;
if (depth <= maxDepth)
EmitValue(fieldValue, fieldInfo.FieldType, emitter, serializer);
else
emitter.Emit(new Scalar("Skipped"));
depth--;
EmitValue(fieldValue, fieldInfo.FieldType, emitter, serializer);
}
emitter.Emit(new MappingEnd());
@ -106,6 +106,12 @@ public class InstanceConverter : IEngineTypeYamlConverter
return;
}
if (value is IEntity entity)
{
emitter.Emit(new Scalar(entity.Id));
return;
}
bool isSequence = Utils.IsEnumerable(declaredType);
if (!isSequence)
@ -118,7 +124,10 @@ public class InstanceConverter : IEngineTypeYamlConverter
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
foreach (object? item in sequence)
serializer(item);
if (value is IEntity sequenceEntity)
emitter.Emit(new Scalar(sequenceEntity.Id));
else
serializer(item);
emitter.Emit(new SequenceEnd());
}
}

View File

@ -7,9 +7,9 @@ namespace Syntriax.Engine.Serialization;
public class EntityFinder
{
private readonly HashSet<IEntity> _entities = [];
private readonly Dictionary<string, IEntity> _entities = [];
public IReadOnlyCollection<IEntity> Entities => _entities;
public IReadOnlyDictionary<string, IEntity> Entities => _entities;
public void FindEntitiesUnder(object @object)
{
@ -23,9 +23,11 @@ public class EntityFinder
return;
}
if (!_entities.Add(entity))
if (Entities.ContainsKey(entity.Id))
return;
_entities.Add(entity.Id, entity);
foreach (PropertyInfo propertyInfo in typeData.Properties)
{
if (propertyInfo.PropertyType?.IsPrimitive ?? true || propertyInfo.PropertyType == typeof(string))

View File

@ -1,4 +1,4 @@
namespace Syntriax.Engine.Serialization;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
public class IgnoreSerializationAttribute : Attribute;

View File

@ -7,7 +7,7 @@ namespace Syntriax.Engine.Serialization;
public static class Serializer
{
private static readonly ISerializer serializer = GetSerializer();
private static ISerializer GetSerializer()
private static ISerializer GetSerializer(EntityFinder? entityFinder = null)
{
SerializerBuilder serializerBuilder = new SerializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
@ -16,6 +16,9 @@ public static class Serializer
foreach (IEngineTypeYamlConverter typeConverter in GetEngineYamlTypeConverters())
serializerBuilder = serializerBuilder.WithTypeConverter(typeConverter);
if (entityFinder is not null)
serializerBuilder = serializerBuilder.WithTypeConverter(new EntityConverter(entityFinder.Entities));
return serializerBuilder.Build();
}
@ -39,7 +42,10 @@ public static class Serializer
public static string Serialize(object instance)
{
return serializer.Serialize(instance);
EntityFinder entityFinder = new();
entityFinder.FindEntitiesUnder(instance);
ISerializer serializer = GetSerializer(entityFinder);
return serializer.Serialize(entityFinder.Entities);
}
public static object Deserialize(string yaml)

View File

@ -9,10 +9,15 @@ internal static class Utils
internal static TypeData GetTypeData(this Type objectType)
{
List<FieldInfo> fieldInfos = GetFieldInfosIncludingBaseClasses(objectType, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public);
List<EventInfo> eventInfos = objectType.GetEvents(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
.OrderBy(ei => ei.Name)
.ToList();
List<FieldInfo> fieldInfos = GetFieldInfosIncludingBaseClasses(objectType, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Public)
.Where(pi => !eventInfos.Any(ei => pi.Name.CompareTo(ei.Name) == 0)).ToList();
List<PropertyInfo> propertyInfos = GetPropertyInfosIncludingBaseClasses(objectType, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public)
.Where(pi => pi.SetMethod is not null)
.Where(pi => pi.SetMethod is not null && !eventInfos.Any(ei => pi.Name.CompareTo(ei.Name) == 0))
.ToList();
return new TypeData(fieldInfos, propertyInfos);