using System; using System.Collections.Generic; using System.Reflection; using Syntriax.Engine.Core.Factory; namespace Syntriax.Engine.Core.Serialization; public class SerializedClass { private const BindingFlags PRIVATE_BINDING_FLAGS = BindingFlags.Instance | BindingFlags.NonPublic; private const BindingFlags PUBLIC_BINDING_FLAGS = BindingFlags.Instance | BindingFlags.Public; public string Type { get; set; } = string.Empty; public Dictionary Public { get; set; } = []; public Dictionary Private { get; set; } = []; public SerializedClass() { } public SerializedClass(object @class) { UpdateClass(@class); } private void UpdateClass(object @class) { Type type = @class.GetType(); Type = type.FullName ?? type.Name; bool shouldSerializeAll = type.HasAttribute(); Public.Clear(); Private.Clear(); foreach (PropertyInfo privatePropertyInfo in Utils.GetPropertyInfosIncludingBaseClasses(type, PRIVATE_BINDING_FLAGS)) { if (privatePropertyInfo.HasAttribute()) continue; if (privatePropertyInfo.SetMethod is null) continue; if (!shouldSerializeAll && !privatePropertyInfo.HasAttribute()) continue; object? value = privatePropertyInfo.GetValue(@class); if (value is IEntity entity) Private.Add(privatePropertyInfo.Name, entity.Id); else Private.Add(privatePropertyInfo.Name, value); } foreach (PropertyInfo publicPropertyInfo in Utils.GetPropertyInfosIncludingBaseClasses(type, PUBLIC_BINDING_FLAGS)) { if (publicPropertyInfo.HasAttribute()) continue; if (publicPropertyInfo.SetMethod is null) continue; if (!shouldSerializeAll && !publicPropertyInfo.HasAttribute()) continue; object? value = publicPropertyInfo.GetValue(@class); if (value is IEntity entity) Public.Add(publicPropertyInfo.Name, entity.Id); else Public.Add(publicPropertyInfo.Name, value); } foreach (FieldInfo privateFieldInfo in Utils.GetFieldInfosIncludingBaseClasses(type, PRIVATE_BINDING_FLAGS)) { if (privateFieldInfo.HasAttribute()) continue; if (!shouldSerializeAll && !privateFieldInfo.HasAttribute()) continue; object? value = privateFieldInfo.GetValue(@class); if (value is IEntity entity) Private.Add(privateFieldInfo.Name, entity.Id); else Private.Add(privateFieldInfo.Name, value); } foreach (FieldInfo publicFieldInfo in Utils.GetFieldInfosIncludingBaseClasses(type, PUBLIC_BINDING_FLAGS)) { if (publicFieldInfo.HasAttribute()) continue; if (!shouldSerializeAll && !publicFieldInfo.HasAttribute()) continue; object? value = publicFieldInfo.GetValue(@class); if (value is IEntity entity) Public.Add(publicFieldInfo.Name, entity.Id); else Public.Add(publicFieldInfo.Name, value); } } public object CreateInstance() { Type type = TypeFactory.GetType(Type); object instance = TypeFactory.Get(type); foreach ((string key, object? value) in Private) AssignVariable(key, type, instance, value, PRIVATE_BINDING_FLAGS); foreach ((string key, object? value) in Public) AssignVariable(key, type, instance, value, PUBLIC_BINDING_FLAGS); return instance; } public object CreateInstance(EntityRegistry? entityRegistry) { if (entityRegistry is null) return CreateInstance(); Type type = TypeFactory.GetType(Type); object instance = TypeFactory.Get(type); foreach ((string key, object? value) in Private) AssignVariable(key, type, instance, value, PRIVATE_BINDING_FLAGS, entityRegistry); foreach ((string key, object? value) in Public) AssignVariable(key, type, instance, value, PUBLIC_BINDING_FLAGS, entityRegistry); return instance; } private static void AssignVariable(string key, Type type, object instance, object? value, BindingFlags bindingFlags, EntityRegistry entityRegistry) { if (type.GetField(key, bindingFlags) is FieldInfo fieldInfo) { if (typeof(IEntity).IsAssignableFrom(fieldInfo.FieldType)) entityRegistry.QueueAssign(value?.ToString() ?? "", (entity) => fieldInfo.SetValue(instance, entity)); else fieldInfo.SetValue(instance, value); } else if (type.GetProperty(key, bindingFlags) is PropertyInfo propertyInfo) { if (typeof(IEntity).IsAssignableFrom(propertyInfo.PropertyType)) entityRegistry.QueueAssign(value?.ToString() ?? "", (entity) => propertyInfo.SetValue(instance, entity)); else propertyInfo.SetValue(instance, value); } } private static void AssignVariable(string key, Type type, object instance, object? value, BindingFlags bindingFlags) { if (type.GetField(key, bindingFlags) is FieldInfo fieldInfo) fieldInfo.SetValue(instance, value); else if (type.GetProperty(key, bindingFlags) is PropertyInfo propertyInfo) propertyInfo.SetValue(instance, value); } }