From 469eea16bb5031f94bb5b8c1ef436750e892d87f Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:06:02 +0800 Subject: [PATCH] update EcsPipeline.Builder add system orders Split EcsPipeline.cs into EcsPipeline.cs and EcsPipeline.Builder.cs Add system orders to EcsPipeline.Builder Implement IEcsModule interface for EcsPipeline.Builder --- src/EcsPipeline.Builder.cs | 489 ++++++++++++++++++++++++++++++++++ src/EcsPipeline.cs | 271 +------------------ src/Injections/Injector.cs | 7 + src/Utils/IConfigContainer.cs | 29 +- 4 files changed, 524 insertions(+), 272 deletions(-) create mode 100644 src/EcsPipeline.Builder.cs diff --git a/src/EcsPipeline.Builder.cs b/src/EcsPipeline.Builder.cs new file mode 100644 index 0000000..2d46b63 --- /dev/null +++ b/src/EcsPipeline.Builder.cs @@ -0,0 +1,489 @@ +using DCFApixels.DragonECS.RunnersCore; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace DCFApixels.DragonECS +{ + public sealed partial class EcsPipeline + { + public class Builder : IEcsModule + { + private const int KEYS_CAPACITY = 4; + private const string BASIC_LAYER = EcsConsts.BASIC_LAYER; + + private readonly HashSet _uniqueTypes = new HashSet(32); + private readonly Dictionary _systems = new Dictionary(KEYS_CAPACITY); + private readonly List _initDeclaredRunners = new List(4); + public readonly LayerList Layers; + public readonly Injector.Builder Injector; + public readonly Configurator Configs; + +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build"); +#endif + + #region Constructors + public Builder(IConfigContainerWriter config = null) + { + if (config == null) { config = new ConfigContainer(); } + Configs = new Configurator(config, this); + + Injector = new Injector.Builder(this); + Injector.AddNode(); + Injector.AddNode(); + Injector.AddNode(); + Injector.AddNode(); + + Layers = new LayerList(this, BASIC_LAYER); + Layers.Insert(EcsConsts.BASIC_LAYER, EcsConsts.PRE_BEGIN_LAYER, EcsConsts.BEGIN_LAYER); + Layers.InsertAfter(EcsConsts.BASIC_LAYER, EcsConsts.END_LAYER, EcsConsts.POST_END_LAYER); + } + #endregion + + #region Add + public Builder Add(IEcsProcess system, int? order = null) + { + return AddInternal(system, string.Empty, order, false); + } + public Builder Add(IEcsProcess system, string layerName, int? order = null) + { + return AddInternal(system, layerName, order, false); + } + public Builder AddUnique(IEcsProcess system, int? order = null) + { + return AddInternal(system, string.Empty, order, true); + } + public Builder AddUnique(IEcsProcess system, string layerName, int? order = null) + { + return AddInternal(system, layerName, order, true); + } + private Builder AddInternal(IEcsProcess system, string layerName, int? settedOrder, bool isUnique) + { + int order; + if (settedOrder.HasValue) + { + order = settedOrder.Value; + } + else + { + order = system is IEcsSystemDefaultOrder defaultOrder ? defaultOrder.Order : 0; + } + + if (string.IsNullOrEmpty(layerName)) + { + layerName = system is IEcsSystemDefaultLayer defaultLayer ? defaultLayer.Layer : BASIC_LAYER; + } + if (!_systems.TryGetValue(layerName, out SystemsList list)) + { + list = new SystemsList(layerName); + _systems.Add(layerName, list); + } + if (_uniqueTypes.Add(system.GetType()) == false && isUnique) + { + return this; + } + list.Add(system, order); + + if (system is IEcsModule module)//если система одновременно явялется и системой и модулем то за один Add будет вызван Add и AddModule + { + AddModule(module); + } + + return this; + } + #endregion + + #region Add other + public Builder AddModule(IEcsModule module) + { + module.Import(this); + return this; + } + public Builder AddRunner() where TRunner : EcsRunner, IEcsRunner, new() + { + _initDeclaredRunners.Add(new InitDeclaredRunner()); + return this; + } + void IEcsModule.Import(Builder into) + { + into.MergeWith(this); + } + private void MergeWith(Builder other) + { + Injector.Add(other.Injector); + foreach (var declaredRunners in other._initDeclaredRunners) + { + _initDeclaredRunners.Add(declaredRunners); + } + foreach (var config in other.Configs.Instance.GetAllConfigs()) + { + Configs.Instance.Set(config.Key, config.Value); + } + Layers.MergeWith(other.Layers); + + foreach (var otherPair in other._systems) + { + if (_systems.TryGetValue(otherPair.Key, out SystemsList selfList) == false) + { + selfList = new SystemsList(otherPair.Key); + _systems.Add(otherPair.Key, selfList); + } + selfList.AddList(otherPair.Value); + } + + //TODO добавить проверку уникальных систем + //сливать множество уникальных нужно после слияния систем + _uniqueTypes.UnionWith(other._uniqueTypes); + + } + #endregion + + #region Remove + public Builder Remove() + { + _uniqueTypes.Remove(typeof(TSystem)); + foreach (var list in _systems.Values) + { + list.RemoveAll(); + } + return this; + } + #endregion + + #region Build + public EcsPipeline Build() + { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + _buildBarker.Begin(); +#endif + SystemsList basicBlockList; + if (_systems.TryGetValue(BASIC_LAYER, out basicBlockList) == false) + { + basicBlockList = new SystemsList(BASIC_LAYER); + _systems.Add(BASIC_LAYER, basicBlockList); + } + int allSystemsLength = 0; + foreach (var item in _systems) + { + if (item.Key == BASIC_LAYER) + { + continue; + } + if (!Layers.Contains(item.Key)) + { + basicBlockList.AddList(item.Value); + } + else + { + allSystemsLength += item.Value.recordsCount; + } + item.Value.Sort(); + } + allSystemsLength += basicBlockList.recordsCount; + basicBlockList.Sort(); + + IEcsProcess[] allSystems = new IEcsProcess[allSystemsLength]; + { + int i = 0; + foreach (var item in Layers) + { + if (_systems.TryGetValue(item, out var list)) + { + for (int j = 0; j < list.recordsCount; j++) + { + allSystems[i++] = list.records[j].system; + } + } + } + } + + EcsPipeline pipeline = new EcsPipeline(Configs.Instance.GetContainer(), Injector, allSystems); + foreach (var item in _initDeclaredRunners) + { + item.Declare(pipeline); + } +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + _buildBarker.End(); +#endif + return pipeline; + } + #endregion + + #region InitDeclaredRunner + private abstract class InitDeclaredRunner + { + public abstract void Declare(EcsPipeline pipeline); + } + private class InitDeclaredRunner : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new() + { + public override void Declare(EcsPipeline pipeline) + { + pipeline.GetRunnerInstance(); + } + } + #endregion + + #region Configurator + public class Configurator + { + private readonly IConfigContainerWriter _configs; + private readonly Builder _builder; + public Configurator(IConfigContainerWriter configs, Builder builder) + { + _configs = configs; + _builder = builder; + } + public IConfigContainerWriter Instance + { + get { return _configs; } + } + public Builder Set(T value) + { + _configs.Set(value); + return _builder; + } + } + #endregion + + #region LayerList + public class LayerList : IEnumerable + { + private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add + + private Builder _source; + private List _layers; + private string _basicLayerName; + + public int Count + { + get { return _layers.Count; } + } + public LayerList(Builder source, string basicLayerName) + { + _source = source; + _layers = new List(16) { basicLayerName, ADD_LAYER }; + _basicLayerName = basicLayerName; + } + + public Builder Add(string newLayer) { return Insert(ADD_LAYER, newLayer); } + public Builder Insert(string targetLayer, string newLayer) + { + if (Contains(newLayer)) { return _source; } + + int index = _layers.IndexOf(targetLayer); + if (index < 0) + { + throw new KeyNotFoundException($"Layer {targetLayer} not found"); + } + _layers.Insert(index, newLayer); + return _source; + } + public Builder InsertAfter(string targetLayer, string newLayer) + { + if (Contains(newLayer)) { return _source; } + + if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER + { + targetLayer = ADD_LAYER; + } + + int index = _layers.IndexOf(targetLayer); + if (index < 0) + { + throw new KeyNotFoundException($"Layer {targetLayer} not found"); + } + + if (++index >= _layers.Count) + { + _layers.Add(newLayer); + } + else + { + _layers.Insert(index, newLayer); + } + return _source; + } + public Builder Move(string targetLayer, string movingLayer) + { + _layers.Remove(movingLayer); + return Insert(targetLayer, movingLayer); + } + public Builder MoveAfter(string targetLayer, string movingLayer) + { + if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER + { + targetLayer = ADD_LAYER; + } + + _layers.Remove(movingLayer); + return InsertAfter(targetLayer, movingLayer); + } + + public Builder Add(params string[] newLayers) { return Insert(ADD_LAYER, newLayers); } + public Builder Insert(string targetLayer, params string[] newLayers) + { + int index = _layers.IndexOf(targetLayer); + if (index < 0) + { + throw new KeyNotFoundException($"Layer {targetLayer} not found"); + } + _layers.InsertRange(index, newLayers.Where(o => !Contains(o))); + return _source; + } + public Builder InsertAfter(string targetLayer, params string[] newLayers) + { + int index = _layers.IndexOf(targetLayer); + if (index < 0) + { + throw new KeyNotFoundException($"Layer {targetLayer} not found"); + } + + if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER + { + targetLayer = ADD_LAYER; + } + + if (++index >= _layers.Count) + { + _layers.AddRange(newLayers.Where(o => !Contains(o))); + } + else + { + _layers.InsertRange(index, newLayers.Where(o => !Contains(o))); + } + return _source; + } + public Builder Move(string targetLayer, params string[] movingLayers) + { + foreach (var movingLayer in movingLayers) + { + _layers.Remove(movingLayer); + } + return Insert(targetLayer, movingLayers); + } + public Builder MoveAfter(string targetLayer, params string[] movingLayers) + { + if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER + { + targetLayer = ADD_LAYER; + } + + foreach (var movingLayer in movingLayers) + { + _layers.Remove(movingLayer); + } + return InsertAfter(targetLayer, movingLayers); + } + + public void MergeWith(LayerList other) + { + HashSet seen = new HashSet(); + List result = new List(); + + List listA = _layers; + List listB = other._layers; + + foreach (string item in listA) + { + seen.Add(item); + } + foreach (string item in listB) + { + if (seen.Add(item) == false) + { + seen.Remove(item); + } + } + + int i = 0, j = 0; + while (i < listA.Count || j < listB.Count) + { + while (i < listA.Count && seen.Contains(listA[i])) + { + result.Add(listA[i]); + i++; + } + while (j < listB.Count && seen.Contains(listB[j])) + { + result.Add(listB[j]); + j++; + } + + if (i < listA.Count) { i++; } + if (j < listB.Count) + { + result.Add(listB[j]); + j++; + } + } + + _layers = result; + } + + public bool Contains(string layer) { return _layers.Contains(layer); } + + public List.Enumerator GetEnumerator() { return _layers.GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return _layers.GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return _layers.GetEnumerator(); } + } + #endregion + + #region SystemsList + private class SystemsList + { + public SystemRecord[] records = new SystemRecord[32]; + public int recordsCount = 0; + public ReadOnlySpan Records { get { return new ReadOnlySpan(records, 1, recordsCount - 1); } } + public SystemsList(string layerName) + { + Add(new SystemsLayerMarkerSystem(layerName), int.MinValue); + } + public void AddList(SystemsList other) + { + for (int i = 1; i < other.recordsCount; i++) + { + var otherRecord = other.records[i]; + Add(otherRecord.system, otherRecord.order); + } + } + public void Add(IEcsProcess system, int order) + { + if (records.Length <= recordsCount) + { + Array.Resize(ref records, recordsCount << 1); + } + records[recordsCount++] = new SystemRecord(system, order); + } + public void RemoveAll() + { + for (int i = 0; i < recordsCount; i++) + { + if (records[i].system is T) + { + records[i] = records[--recordsCount]; + } + } + } + public void Sort() + { + //Игнорирую первую систему, так как это чисто система с названием слоя + Array.Sort(records, 1, recordsCount - 1); + } + } + private readonly struct SystemRecord : IComparable + { + public readonly IEcsProcess system; + public readonly int order; + public SystemRecord(IEcsProcess system, int order) + { + this.system = system; + this.order = order; + } + public int CompareTo(SystemRecord other) { return order - other.order; } + } + #endregion + } + } +} \ No newline at end of file diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index 504c920..082e108 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -25,8 +25,15 @@ namespace DCFApixels.DragonECS } [MetaColor(MetaColor.DragonRose)] [MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.OTHER_GROUP)] + [MetaDescription(EcsConsts.AUTHOR, "...")] + public interface IEcsSystemDefaultOrder : IEcsProcess + { + int Order { get; } + } + [MetaColor(MetaColor.DragonRose)] + [MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.OTHER_GROUP)] [MetaDescription(EcsConsts.AUTHOR, "Container and engine for systems. Responsible for configuring the execution order of systems, providing a mechanism for messaging between systems, and a dependency injection mechanism.")] - public sealed class EcsPipeline + public sealed partial class EcsPipeline { private readonly IConfigContainer _configs; private Injector.Builder _injectorBuilder; @@ -204,265 +211,6 @@ namespace DCFApixels.DragonECS { return new Builder(config); } - public class Builder - { - private const int KEYS_CAPACITY = 4; - private HashSet _uniqueTypes; - private readonly Dictionary> _systems; - private readonly string _basicLayer; - public readonly LayerList Layers; - private readonly Configurator _configurator; - private readonly Injector.Builder _injector; -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build"); -#endif - private List _initDeclaredRunners = new List(4); - - public Configurator Configs - { - get { return _configurator; } - } - public Injector.Builder Injector - { - get { return _injector; } - } - public Builder(IConfigContainerWriter config = null) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - _buildBarker.Begin(); -#endif - if (config == null) { config = new ConfigContainer(); } - _configurator = new Configurator(config, this); - - _injector = new Injector.Builder(this); - _injector.AddNode(); - _injector.AddNode(); - _injector.AddNode(); - _injector.AddNode(); - - _basicLayer = EcsConsts.BASIC_LAYER; - Layers = new LayerList(this, _basicLayer); - Layers.Insert(EcsConsts.BASIC_LAYER, EcsConsts.PRE_BEGIN_LAYER, EcsConsts.BEGIN_LAYER); - Layers.InsertAfter(EcsConsts.BASIC_LAYER, EcsConsts.END_LAYER, EcsConsts.POST_END_LAYER); - - _uniqueTypes = new HashSet(); - _systems = new Dictionary>(KEYS_CAPACITY); - } - public Builder AddRunner() where TRunner : EcsRunner, IEcsRunner, new() - { - _initDeclaredRunners.Add(new InitDeclaredRunner()); - return this; - } - public Builder Add(IEcsProcess system, string layerName = null) - { - AddInternal(system, layerName, false); - return this; - } - public Builder AddUnique(IEcsProcess system, string layerName = null) - { - AddInternal(system, layerName, true); - return this; - } - public Builder Remove() - { - _uniqueTypes.Remove(typeof(TSystem)); - foreach (var list in _systems.Values) - { - list.RemoveAll(o => o is TSystem); - } - return this; - } - private void AddInternal(IEcsProcess system, string layerName, bool isUnique) - { - if (string.IsNullOrEmpty(layerName)) - { - layerName = system is IEcsSystemDefaultLayer defaultLayer ? defaultLayer.Layer : _basicLayer; - } - List list; - if (!_systems.TryGetValue(layerName, out list)) - { - list = new List { new SystemsLayerMarkerSystem(layerName) }; - _systems.Add(layerName, list); - } - if (_uniqueTypes.Add(system.GetType()) == false && isUnique) - { - return; - } - list.Add(system); - - if (system is IEcsModule module)//если система одновременно явялется и системой и модулем то за один Add будет вызван Add и AddModule - { - AddModule(module); - } - } - public Builder AddModule(IEcsModule module) - { - module.Import(this); - return this; - } - public EcsPipeline Build() - { - List result = new List(32); - List basicBlockList; - if (_systems.TryGetValue(_basicLayer, out basicBlockList) == false) - { - basicBlockList = new List(); - } - foreach (var item in _systems) - { - if (!Layers.Contains(item.Key)) - basicBlockList.AddRange(item.Value); - } - foreach (var item in Layers) - { - if (_systems.TryGetValue(item, out var list)) - result.AddRange(list); - } - EcsPipeline pipeline = new EcsPipeline(_configurator.Instance.GetContainer(), _injector, result.ToArray()); - foreach (var item in _initDeclaredRunners) - { - item.Declare(pipeline); - } -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - _buildBarker.End(); -#endif - return pipeline; - } - - private abstract class InitDeclaredRunner - { - public abstract void Declare(EcsPipeline pipeline); - } - private class InitDeclaredRunner : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new() - { - public override void Declare(EcsPipeline pipeline) - { - pipeline.GetRunnerInstance(); - } - } - public class Configurator - { - private readonly IConfigContainerWriter _configs; - private readonly Builder _builder; - public Configurator(IConfigContainerWriter configs, Builder builder) - { - _configs = configs; - _builder = builder; - } - public IConfigContainerWriter Instance - { - get { return _configs; } - } - public Builder Set(T value) - { - _configs.Set(value); - return _builder; - } - } - public class LayerList : IEnumerable - { - private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add - - private Builder _source; - private List _layers; - private string _basicLayerName; - - public LayerList(Builder source, string basicLayerName) - { - _source = source; - _layers = new List(16) { basicLayerName, ADD_LAYER }; - _basicLayerName = basicLayerName; - } - - public Builder Add(string newLayer) => Insert(ADD_LAYER, newLayer); - public Builder Insert(string targetLayer, string newLayer) - { - if (Contains(newLayer)) return _source; - - int index = _layers.IndexOf(targetLayer); - if (index < 0) - throw new KeyNotFoundException($"Layer {targetLayer} not found"); - _layers.Insert(index, newLayer); - return _source; - } - public Builder InsertAfter(string targetLayer, string newLayer) - { - if (Contains(newLayer)) return _source; - - if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER - targetLayer = ADD_LAYER; - - int index = _layers.IndexOf(targetLayer); - if (index < 0) - throw new KeyNotFoundException($"Layer {targetLayer} not found"); - - if (++index >= _layers.Count) - _layers.Add(newLayer); - else - _layers.Insert(index, newLayer); - return _source; - } - public Builder Move(string targetLayer, string movingLayer) - { - _layers.Remove(movingLayer); - return Insert(targetLayer, movingLayer); - } - public Builder MoveAfter(string targetLayer, string movingLayer) - { - if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER - targetLayer = ADD_LAYER; - - _layers.Remove(movingLayer); - return InsertAfter(targetLayer, movingLayer); - } - - public Builder Add(params string[] newLayers) => Insert(ADD_LAYER, newLayers); - public Builder Insert(string targetLayer, params string[] newLayers) - { - int index = _layers.IndexOf(targetLayer); - if (index < 0) - throw new KeyNotFoundException($"Layer {targetLayer} not found"); - _layers.InsertRange(index, newLayers.Where(o => !Contains(o))); - return _source; - } - public Builder InsertAfter(string targetLayer, params string[] newLayers) - { - int index = _layers.IndexOf(targetLayer); - if (index < 0) - throw new KeyNotFoundException($"Layer {targetLayer} not found"); - - if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER - targetLayer = ADD_LAYER; - - if (++index >= _layers.Count) - _layers.AddRange(newLayers.Where(o => !Contains(o))); - else - _layers.InsertRange(index, newLayers.Where(o => !Contains(o))); - return _source; - } - public Builder Move(string targetLayer, params string[] movingLayers) - { - foreach (var movingLayer in movingLayers) - _layers.Remove(movingLayer); - return Insert(targetLayer, movingLayers); - } - public Builder MoveAfter(string targetLayer, params string[] movingLayers) - { - if (targetLayer == _basicLayerName) // нужно чтобы метод Add работал правильно. _basicLayerName и ADD_LAYER считается одним слоем, поэтому Before = _basicLayerName After = ADD_LAYER - targetLayer = ADD_LAYER; - - foreach (var movingLayer in movingLayers) - _layers.Remove(movingLayer); - return InsertAfter(targetLayer, movingLayers); - } - - public bool Contains(string layer) => _layers.Contains(layer); - - public List.Enumerator GetEnumerator() => _layers.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => _layers.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => _layers.GetEnumerator(); - } - } #endregion } @@ -511,7 +259,8 @@ namespace DCFApixels.DragonECS public class SystemsLayerMarkerSystem : IEcsProcess { public readonly string name; - public SystemsLayerMarkerSystem(string name) => this.name = name; + public SystemsLayerMarkerSystem(string name) { this.name = name; } + public override string ToString() { return name; } } #endregion diff --git a/src/Injections/Injector.cs b/src/Injections/Injector.cs index 48b078b..ecc0c7d 100644 --- a/src/Injections/Injector.cs +++ b/src/Injections/Injector.cs @@ -179,6 +179,13 @@ namespace DCFApixels.DragonECS } return _instance; } + public void Add(Builder other) + { + foreach (var item in other._initInjections) + { + _initInjections.Add(item); + } + } private abstract class InitInjectBase { diff --git a/src/Utils/IConfigContainer.cs b/src/Utils/IConfigContainer.cs index 7cb0e15..4a57087 100644 --- a/src/Utils/IConfigContainer.cs +++ b/src/Utils/IConfigContainer.cs @@ -10,20 +10,21 @@ namespace DCFApixels.DragonECS bool Has(); T Get(); bool TryGet(out T value); - IEnumerable GetAllConfigs(); + IEnumerable> GetAllConfigs(); } public interface IConfigContainerWriter { int Count { get; } void Set(T value); + void Set(Type type, object value); bool Has(); T Get(); bool TryGet(out T value); void Remove(); - IEnumerable GetAllConfigs(); + IEnumerable> GetAllConfigs(); IConfigContainer GetContainer(); } - public sealed class ConfigContainer : IConfigContainer, IConfigContainerWriter, IEnumerable + public sealed class ConfigContainer : IConfigContainer, IConfigContainerWriter, IEnumerable> { public static readonly ConfigContainer Empty = new ConfigContainer(); @@ -66,6 +67,15 @@ namespace DCFApixels.DragonECS _storage[typeof(T)] = value; return this; } + public ConfigContainer Set(Type type, object value) + { + _storage[type] = value; + return this; + } + void IConfigContainerWriter.Set(Type type, object value) + { + Set(type, value); + } void IConfigContainerWriter.Set(T value) { Set(value); @@ -76,17 +86,14 @@ namespace DCFApixels.DragonECS value = rawValue == null ? default : (T)rawValue; return result; } - public IConfigContainer GetContainer() + public IConfigContainer GetContainer() { return this; } + public IEnumerable> GetAllConfigs() { - return this; + return _storage; } - public IEnumerable GetAllConfigs() + public IEnumerator> GetEnumerator() { - return _storage.Values; - } - public IEnumerator GetEnumerator() - { - return _storage.Values.GetEnumerator(); + return _storage.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() {