chore: experimentations
This commit is contained in:
parent
2637f99456
commit
35a75d993b
@ -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());
|
||||
}
|
||||
}
|
@ -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))
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Syntriax.Engine.Serialization;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
|
||||
public class IgnoreSerializationAttribute : Attribute;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user