chore: experimentations
This commit is contained in:
parent
2637f99456
commit
35a75d993b
@ -1,6 +1,6 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Syntriax.Engine.Core;
|
||||||
using Syntriax.Engine.Core.Factory;
|
using Syntriax.Engine.Core.Factory;
|
||||||
|
|
||||||
using YamlDotNet.Core;
|
using YamlDotNet.Core;
|
||||||
@ -9,17 +9,15 @@ using YamlDotNet.Serialization;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Serialization;
|
namespace Syntriax.Engine.Serialization;
|
||||||
|
|
||||||
public class InstanceConverter : IEngineTypeYamlConverter
|
public class EntityConverter(IReadOnlyDictionary<string, IEntity> entities) : IYamlTypeConverter
|
||||||
{
|
{
|
||||||
private int depth = 0;
|
private readonly IReadOnlyDictionary<string, IEntity> Entities = entities;
|
||||||
private int maxDepth = 5;
|
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)
|
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
|
||||||
{
|
{
|
||||||
if (depth > maxDepth)
|
|
||||||
return null;
|
|
||||||
parser.Consume<MappingStart>();
|
parser.Consume<MappingStart>();
|
||||||
|
|
||||||
TypeContainer typeContainer = (TypeContainer)rootDeserializer(typeof(TypeContainer))!;
|
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)
|
if (type.GetField(key, BindingFlags.Instance | BindingFlags.NonPublic) is FieldInfo fieldInfo)
|
||||||
{
|
{
|
||||||
depth++;
|
|
||||||
object? fieldValue = rootDeserializer(fieldInfo.FieldType);
|
object? fieldValue = rootDeserializer(fieldInfo.FieldType);
|
||||||
depth--;
|
|
||||||
fieldInfo.SetValue(instance, fieldValue);
|
fieldInfo.SetValue(instance, fieldValue);
|
||||||
}
|
}
|
||||||
else if (type.GetProperty(key) is PropertyInfo propertyInfo)
|
else if (type.GetProperty(key) is PropertyInfo propertyInfo)
|
||||||
{
|
{
|
||||||
depth++;
|
|
||||||
object? propertyValue = rootDeserializer(propertyInfo.PropertyType);
|
object? propertyValue = rootDeserializer(propertyInfo.PropertyType);
|
||||||
depth--;
|
|
||||||
propertyInfo.SetValue(instance, propertyValue);
|
propertyInfo.SetValue(instance, propertyValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -55,6 +49,19 @@ public class InstanceConverter : IEngineTypeYamlConverter
|
|||||||
|
|
||||||
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
|
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());
|
emitter.Emit(new MappingStart());
|
||||||
serializer(new TypeContainer(value), typeof(TypeContainer));
|
serializer(new TypeContainer(value), typeof(TypeContainer));
|
||||||
|
|
||||||
@ -68,12 +75,7 @@ public class InstanceConverter : IEngineTypeYamlConverter
|
|||||||
emitter.Emit(new Scalar(propertyInfo.Name));
|
emitter.Emit(new Scalar(propertyInfo.Name));
|
||||||
object? propertyValue = propertyInfo.GetValue(value);
|
object? propertyValue = propertyInfo.GetValue(value);
|
||||||
|
|
||||||
depth++;
|
EmitValue(propertyValue, propertyInfo.PropertyType, emitter, serializer);
|
||||||
if (depth <= maxDepth)
|
|
||||||
EmitValue(propertyValue, propertyInfo.PropertyType, emitter, serializer);
|
|
||||||
else
|
|
||||||
emitter.Emit(new Scalar("Skipped"));
|
|
||||||
depth--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (FieldInfo fieldInfo in typeData.Fields)
|
foreach (FieldInfo fieldInfo in typeData.Fields)
|
||||||
@ -81,18 +83,16 @@ public class InstanceConverter : IEngineTypeYamlConverter
|
|||||||
if (fieldInfo.HasAttribute<System.Runtime.CompilerServices.CompilerGeneratedAttribute>())
|
if (fieldInfo.HasAttribute<System.Runtime.CompilerServices.CompilerGeneratedAttribute>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!fieldInfo.HasAttribute<SerializeAttribute>())
|
if (fieldInfo.HasAttribute<IgnoreSerializationAttribute>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// if (!fieldInfo.HasAttribute<SerializeAttribute>())
|
||||||
|
// continue;
|
||||||
|
|
||||||
emitter.Emit(new Scalar(fieldInfo.Name));
|
emitter.Emit(new Scalar(fieldInfo.Name));
|
||||||
object? fieldValue = fieldInfo.GetValue(value);
|
object? fieldValue = fieldInfo.GetValue(value);
|
||||||
|
|
||||||
depth++;
|
EmitValue(fieldValue, fieldInfo.FieldType, emitter, serializer);
|
||||||
if (depth <= maxDepth)
|
|
||||||
EmitValue(fieldValue, fieldInfo.FieldType, emitter, serializer);
|
|
||||||
else
|
|
||||||
emitter.Emit(new Scalar("Skipped"));
|
|
||||||
depth--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitter.Emit(new MappingEnd());
|
emitter.Emit(new MappingEnd());
|
||||||
@ -106,6 +106,12 @@ public class InstanceConverter : IEngineTypeYamlConverter
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value is IEntity entity)
|
||||||
|
{
|
||||||
|
emitter.Emit(new Scalar(entity.Id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool isSequence = Utils.IsEnumerable(declaredType);
|
bool isSequence = Utils.IsEnumerable(declaredType);
|
||||||
|
|
||||||
if (!isSequence)
|
if (!isSequence)
|
||||||
@ -118,7 +124,10 @@ public class InstanceConverter : IEngineTypeYamlConverter
|
|||||||
|
|
||||||
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
|
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
|
||||||
foreach (object? item in sequence)
|
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());
|
emitter.Emit(new SequenceEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,9 +7,9 @@ namespace Syntriax.Engine.Serialization;
|
|||||||
|
|
||||||
public class EntityFinder
|
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)
|
public void FindEntitiesUnder(object @object)
|
||||||
{
|
{
|
||||||
@ -23,9 +23,11 @@ public class EntityFinder
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_entities.Add(entity))
|
if (Entities.ContainsKey(entity.Id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_entities.Add(entity.Id, entity);
|
||||||
|
|
||||||
foreach (PropertyInfo propertyInfo in typeData.Properties)
|
foreach (PropertyInfo propertyInfo in typeData.Properties)
|
||||||
{
|
{
|
||||||
if (propertyInfo.PropertyType?.IsPrimitive ?? true || propertyInfo.PropertyType == typeof(string))
|
if (propertyInfo.PropertyType?.IsPrimitive ?? true || propertyInfo.PropertyType == typeof(string))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Serialization;
|
namespace Syntriax.Engine.Serialization;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
|
||||||
public class IgnoreSerializationAttribute : Attribute;
|
public class IgnoreSerializationAttribute : Attribute;
|
||||||
|
@ -7,7 +7,7 @@ namespace Syntriax.Engine.Serialization;
|
|||||||
public static class Serializer
|
public static class Serializer
|
||||||
{
|
{
|
||||||
private static readonly ISerializer serializer = GetSerializer();
|
private static readonly ISerializer serializer = GetSerializer();
|
||||||
private static ISerializer GetSerializer()
|
private static ISerializer GetSerializer(EntityFinder? entityFinder = null)
|
||||||
{
|
{
|
||||||
SerializerBuilder serializerBuilder = new SerializerBuilder()
|
SerializerBuilder serializerBuilder = new SerializerBuilder()
|
||||||
.WithNamingConvention(PascalCaseNamingConvention.Instance)
|
.WithNamingConvention(PascalCaseNamingConvention.Instance)
|
||||||
@ -16,6 +16,9 @@ public static class Serializer
|
|||||||
foreach (IEngineTypeYamlConverter typeConverter in GetEngineYamlTypeConverters())
|
foreach (IEngineTypeYamlConverter typeConverter in GetEngineYamlTypeConverters())
|
||||||
serializerBuilder = serializerBuilder.WithTypeConverter(typeConverter);
|
serializerBuilder = serializerBuilder.WithTypeConverter(typeConverter);
|
||||||
|
|
||||||
|
if (entityFinder is not null)
|
||||||
|
serializerBuilder = serializerBuilder.WithTypeConverter(new EntityConverter(entityFinder.Entities));
|
||||||
|
|
||||||
return serializerBuilder.Build();
|
return serializerBuilder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +42,10 @@ public static class Serializer
|
|||||||
|
|
||||||
public static string Serialize(object instance)
|
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)
|
public static object Deserialize(string yaml)
|
||||||
|
@ -9,10 +9,15 @@ internal static class Utils
|
|||||||
|
|
||||||
internal static TypeData GetTypeData(this Type objectType)
|
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)
|
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();
|
.ToList();
|
||||||
|
|
||||||
return new TypeData(fieldInfos, propertyInfos);
|
return new TypeData(fieldInfos, propertyInfos);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user