From ac2e160abbcfe04aaea71ff4139038efdb95c95a Mon Sep 17 00:00:00 2001 From: Syntriax Date: Sun, 26 Oct 2025 22:34:50 +0300 Subject: [PATCH] refactor!: Identifiable interface extracted from IEntity --- Engine.Core/Abstract/IEntity.cs | 16 +------- Engine.Core/Abstract/IHasId.cs | 20 ++++++++++ Engine.Core/BaseEntity.cs | 2 +- Engine.Core/Serialization/EntityRegistry.cs | 39 ------------------- .../Serialization/IdentifiableRegistry.cs | 39 +++++++++++++++++++ Engine.Core/Serialization/SerializedClass.cs | 34 ++++++++-------- .../Abstract/IEngineTypeYamlConverter.cs | 2 +- .../BehaviourControllerConverter.cs | 2 +- .../Converters/BehaviourConverter.cs | 2 +- .../Converters/EngineTypeYamlConverterBase.cs | 4 +- .../Converters/StateEnableConverter.cs | 2 +- .../Converters/UniverseObjectConverter.cs | 2 +- .../Engine.Integration.Yaml/YamlSerializer.cs | 18 ++++----- 13 files changed, 94 insertions(+), 88 deletions(-) create mode 100644 Engine.Core/Abstract/IHasId.cs delete mode 100644 Engine.Core/Serialization/EntityRegistry.cs create mode 100644 Engine.Core/Serialization/IdentifiableRegistry.cs diff --git a/Engine.Core/Abstract/IEntity.cs b/Engine.Core/Abstract/IEntity.cs index 53a719a..0903fa4 100644 --- a/Engine.Core/Abstract/IEntity.cs +++ b/Engine.Core/Abstract/IEntity.cs @@ -3,18 +3,4 @@ namespace Engine.Core; /// /// Represents a basic entity in the engine. /// -public interface IEntity : IInitializable, IHasStateEnable -{ - /// - /// Event triggered when the of the changes. - /// The string action parameter is the previous of the . - /// - Event OnIdChanged { get; } - - /// - /// The ID of the . - /// - string Id { get; set; } - - readonly record struct IdChangedArguments(string PreviousId); -} +public interface IEntity : IInitializable, IIdentifiable, IHasStateEnable; diff --git a/Engine.Core/Abstract/IHasId.cs b/Engine.Core/Abstract/IHasId.cs new file mode 100644 index 0000000..c4cd50a --- /dev/null +++ b/Engine.Core/Abstract/IHasId.cs @@ -0,0 +1,20 @@ +namespace Engine.Core; + +/// +/// Represents any instance in the engine with an id. +/// +public interface IIdentifiable +{ + /// + /// Event triggered when the of the changes. + /// The string action parameter is the previous of the . + /// + Event OnIdChanged { get; } + + /// + /// The ID of the . + /// + string Id { get; set; } + + readonly record struct IdChangedArguments(string PreviousId); +} diff --git a/Engine.Core/BaseEntity.cs b/Engine.Core/BaseEntity.cs index a16b072..f848e3d 100644 --- a/Engine.Core/BaseEntity.cs +++ b/Engine.Core/BaseEntity.cs @@ -4,7 +4,7 @@ namespace Engine.Core; public abstract class BaseEntity : IEntity { - public Event OnIdChanged { get; } = new(); + public Event OnIdChanged { get; } = new(); public Event OnInitialized { get; } = new(); public Event OnFinalized { get; } = new(); public Event OnStateEnableAssigned { get; } = new(); diff --git a/Engine.Core/Serialization/EntityRegistry.cs b/Engine.Core/Serialization/EntityRegistry.cs deleted file mode 100644 index 6339ba1..0000000 --- a/Engine.Core/Serialization/EntityRegistry.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Engine.Core.Serialization; - -public class EntityRegistry -{ - public Event OnEntityRegistered = null!; - - private readonly Dictionary?> assignCallbacks = []; - private readonly Dictionary registeredEntities = []; - public IReadOnlyDictionary RegisteredEntities => registeredEntities; - - public void Add(IEntity entity) - { - if (registeredEntities.TryAdd(entity.Id, entity)) - OnEntityRegistered?.Invoke(this, new(entity)); - } - - public void QueueAssign(string id, Action setMethod) - { - assignCallbacks.TryAdd(id, null); - assignCallbacks[id] = assignCallbacks[id] + setMethod; - } - - public void AssignAll() - { - foreach ((string id, Action? action) in assignCallbacks) - action?.Invoke(registeredEntities[id]); - } - - public void Reset() - { - assignCallbacks.Clear(); - registeredEntities.Clear(); - } - - public readonly record struct EntityRegisteredArguments(IEntity Entity); -} diff --git a/Engine.Core/Serialization/IdentifiableRegistry.cs b/Engine.Core/Serialization/IdentifiableRegistry.cs new file mode 100644 index 0000000..a69e160 --- /dev/null +++ b/Engine.Core/Serialization/IdentifiableRegistry.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; + +namespace Engine.Core.Serialization; + +public class IdentifiableRegistry +{ + public Event OnEntityRegistered = null!; + + private readonly Dictionary?> assignCallbacks = []; + private readonly Dictionary registeredEntities = []; + public IReadOnlyDictionary RegisteredEntities => registeredEntities; + + public void Add(IIdentifiable identifiable) + { + if (registeredEntities.TryAdd(identifiable.Id, identifiable)) + OnEntityRegistered?.Invoke(this, new(identifiable)); + } + + public void QueueAssign(string id, Action setMethod) + { + assignCallbacks.TryAdd(id, null); + assignCallbacks[id] = assignCallbacks[id] + setMethod; + } + + public void AssignAll() + { + foreach ((string id, Action? action) in assignCallbacks) + action?.Invoke(registeredEntities[id]); + } + + public void Reset() + { + assignCallbacks.Clear(); + registeredEntities.Clear(); + } + + public readonly record struct EntityRegisteredArguments(IIdentifiable Entity); +} diff --git a/Engine.Core/Serialization/SerializedClass.cs b/Engine.Core/Serialization/SerializedClass.cs index 803c83b..4abe1b6 100644 --- a/Engine.Core/Serialization/SerializedClass.cs +++ b/Engine.Core/Serialization/SerializedClass.cs @@ -43,8 +43,8 @@ public class SerializedClass continue; object? value = privatePropertyInfo.GetValue(@class); - if (value is IEntity entity) - Private.Add(privatePropertyInfo.Name, entity.Id); + if (value is IIdentifiable identifiable) + Private.Add(privatePropertyInfo.Name, identifiable.Id); else Private.Add(privatePropertyInfo.Name, value); } @@ -61,8 +61,8 @@ public class SerializedClass continue; object? value = publicPropertyInfo.GetValue(@class); - if (value is IEntity entity) - Public.Add(publicPropertyInfo.Name, entity.Id); + if (value is IIdentifiable identifiable) + Public.Add(publicPropertyInfo.Name, identifiable.Id); else Public.Add(publicPropertyInfo.Name, value); } @@ -76,8 +76,8 @@ public class SerializedClass continue; object? value = privateFieldInfo.GetValue(@class); - if (value is IEntity entity) - Private.Add(privateFieldInfo.Name, entity.Id); + if (value is IIdentifiable identifiable) + Private.Add(privateFieldInfo.Name, identifiable.Id); else Private.Add(privateFieldInfo.Name, value); } @@ -91,8 +91,8 @@ public class SerializedClass continue; object? value = publicFieldInfo.GetValue(@class); - if (value is IEntity entity) - Public.Add(publicFieldInfo.Name, entity.Id); + if (value is IIdentifiable identifiable) + Public.Add(publicFieldInfo.Name, identifiable.Id); else Public.Add(publicFieldInfo.Name, value); } @@ -112,36 +112,36 @@ public class SerializedClass return instance; } - public object CreateInstance(EntityRegistry? entityRegistry) + public object CreateInstance(IdentifiableRegistry? identifiableRegistry) { - if (entityRegistry is null) + if (identifiableRegistry 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); + AssignVariable(key, type, instance, value, PRIVATE_BINDING_FLAGS, identifiableRegistry); foreach ((string key, object? value) in Public) - AssignVariable(key, type, instance, value, PUBLIC_BINDING_FLAGS, entityRegistry); + AssignVariable(key, type, instance, value, PUBLIC_BINDING_FLAGS, identifiableRegistry); return instance; } - private static void AssignVariable(string key, Type type, object instance, object? value, BindingFlags bindingFlags, EntityRegistry entityRegistry) + private static void AssignVariable(string key, Type type, object instance, object? value, BindingFlags bindingFlags, IdentifiableRegistry identifiableRegistry) { if (type.GetField(key, bindingFlags) is FieldInfo fieldInfo) { - if (typeof(IEntity).IsAssignableFrom(fieldInfo.FieldType)) - entityRegistry.QueueAssign(value?.ToString() ?? "", (entity) => fieldInfo.SetValue(instance, entity)); + if (typeof(IIdentifiable).IsAssignableFrom(fieldInfo.FieldType)) + identifiableRegistry.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)); + if (typeof(IIdentifiable).IsAssignableFrom(propertyInfo.PropertyType)) + identifiableRegistry.QueueAssign(value?.ToString() ?? "", (entity) => propertyInfo.SetValue(instance, entity)); else propertyInfo.SetValue(instance, value); } diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs index 873b796..f641442 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/Abstract/IEngineTypeYamlConverter.cs @@ -8,6 +8,6 @@ namespace Engine.Serializers.Yaml; public interface IEngineTypeYamlConverter : IYamlTypeConverter { YamlSerializer Serializer { get; set; } - EntityRegistry EntityRegistry { get; set; } + IdentifiableRegistry IdentifiableRegistry { get; set; } IProgressionTracker ProgressionTracker { get; set; } } diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourControllerConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourControllerConverter.cs index 89391b4..530ae2c 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourControllerConverter.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourControllerConverter.cs @@ -36,7 +36,7 @@ public class BehaviourControllerConverter : EngineTypeYamlSerializerBase().Value; if (value.CompareTo(nameof(IBehaviourController.StateEnable)) != 0) diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourConverter.cs index abc3b97..a475f96 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourConverter.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/BehaviourConverter.cs @@ -36,7 +36,7 @@ public class BehaviourConverter : EngineTypeYamlSerializerBase throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; ProgressionTracker.Set(isTrackingController ? .5f : ProgressionTracker.Progression, $"Creating {instanceSerializedClass.Type}"); - behaviour = (IBehaviour)instanceSerializedClass.CreateInstance(EntityRegistry); + behaviour = (IBehaviour)instanceSerializedClass.CreateInstance(IdentifiableRegistry); if (parser.Consume().Value.CompareTo(nameof(IBehaviour.StateEnable)) != 0) throw new(); diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/EngineTypeYamlConverterBase.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/EngineTypeYamlConverterBase.cs index 134e922..99167ee 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/EngineTypeYamlConverterBase.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/EngineTypeYamlConverterBase.cs @@ -12,7 +12,7 @@ public abstract class EngineTypeYamlSerializerBase : IEngineTypeYamlConverter { protected const string SERIALIZED_SCALAR_NAME = "Properties"; - public EntityRegistry EntityRegistry { get; set; } = null!; + public IdentifiableRegistry IdentifiableRegistry { get; set; } = null!; public YamlSerializer Serializer { get; set; } = null!; public IProgressionTracker ProgressionTracker { get; set; } = null!; @@ -24,7 +24,7 @@ public abstract class EngineTypeYamlSerializerBase : IEngineTypeYamlConverter T? result = Read(parser, type, rootDeserializer); if (result is IEntity entity) - EntityRegistry.Add(entity); + IdentifiableRegistry.Add(entity); return result; } diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/StateEnableConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/StateEnableConverter.cs index 9c317b0..d5c0bc0 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/StateEnableConverter.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/StateEnableConverter.cs @@ -29,7 +29,7 @@ public class StateEnableConverter : EngineTypeYamlSerializerBase if (parser.Consume().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; - stateEnable = (IStateEnable)instanceSerializedClass.CreateInstance(EntityRegistry); + stateEnable = (IStateEnable)instanceSerializedClass.CreateInstance(IdentifiableRegistry); parser.Consume(); diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/UniverseObjectConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/UniverseObjectConverter.cs index c99bc9b..0c7f919 100644 --- a/Engine.Integration/Engine.Integration.Yaml/Converters/UniverseObjectConverter.cs +++ b/Engine.Integration/Engine.Integration.Yaml/Converters/UniverseObjectConverter.cs @@ -40,7 +40,7 @@ public class UniverseObjectSerializer : EngineTypeYamlSerializerBase().Value.CompareTo(nameof(IUniverseObject.StateEnable)) != 0) throw new(); diff --git a/Engine.Integration/Engine.Integration.Yaml/YamlSerializer.cs b/Engine.Integration/Engine.Integration.Yaml/YamlSerializer.cs index 1dfadd1..6df1e67 100644 --- a/Engine.Integration/Engine.Integration.Yaml/YamlSerializer.cs +++ b/Engine.Integration/Engine.Integration.Yaml/YamlSerializer.cs @@ -17,14 +17,14 @@ public class YamlSerializer : Core.Serialization.ISerializer private readonly YamlDotNet.Serialization.ISerializer serializer = null!; private readonly YamlDotNet.Serialization.IDeserializer deserializer = null!; - private readonly EntityRegistry entityRegistry = null!; + private readonly IdentifiableRegistry identifiableRegistry = null!; private readonly IProgressionTracker progressionTracker = null!; private readonly System.Threading.Lock Lock = new(); public YamlSerializer() { - entityRegistry = new(); + identifiableRegistry = new(); progressionTracker = new ProgressionTracker(); SerializerBuilder serializerBuilder = new SerializerBuilder() @@ -37,7 +37,7 @@ public class YamlSerializer : Core.Serialization.ISerializer foreach (IEngineTypeYamlConverter typeConverter in GetEngineYamlTypeConverters()) { typeConverter.Serializer = this; - typeConverter.EntityRegistry = entityRegistry; + typeConverter.IdentifiableRegistry = identifiableRegistry; typeConverter.ProgressionTracker = progressionTracker; deserializerBuilder = deserializerBuilder.WithTypeConverter(typeConverter); @@ -66,9 +66,9 @@ public class YamlSerializer : Core.Serialization.ISerializer { lock (Lock) { - entityRegistry.Reset(); + identifiableRegistry.Reset(); object result = deserializer.Deserialize(configuration)!; - entityRegistry.AssignAll(); + identifiableRegistry.AssignAll(); return result; } } @@ -77,9 +77,9 @@ public class YamlSerializer : Core.Serialization.ISerializer { lock (Lock) { - entityRegistry.Reset(); + identifiableRegistry.Reset(); object result = deserializer.Deserialize(configuration, type)!; - entityRegistry.AssignAll(); + identifiableRegistry.AssignAll(); return result; } } @@ -88,9 +88,9 @@ public class YamlSerializer : Core.Serialization.ISerializer { lock (Lock) { - entityRegistry.Reset(); + identifiableRegistry.Reset(); T result = deserializer.Deserialize(configuration); - entityRegistry.AssignAll(); + identifiableRegistry.AssignAll(); return result; } }