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 isFullySerializable = 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 (!isFullySerializable && !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 (!isFullySerializable && !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 (!isFullySerializable && !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 (!isFullySerializable && !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) if (type.GetField(key, PRIVATE_BINDING_FLAGS) is FieldInfo fieldInfo) fieldInfo.SetValue(instance, value); else if (type.GetProperty(key, PRIVATE_BINDING_FLAGS) is PropertyInfo propertyInfo) propertyInfo.SetValue(instance, value); foreach ((string key, object? value) in Public) if (type.GetField(key, PUBLIC_BINDING_FLAGS) is FieldInfo fieldInfo) fieldInfo.SetValue(instance, value); else if (type.GetProperty(key, PUBLIC_BINDING_FLAGS) is PropertyInfo propertyInfo) propertyInfo.SetValue(instance, value); return instance; } }