mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
Resolve TODO
This commit is contained in:
parent
693a0615e0
commit
5591a3f5b1
@ -196,7 +196,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
self.Print("");
|
||||
}
|
||||
//TODO PrintJson не возможно будет добавлено когда-то
|
||||
//TODO PrintJson возможно будет добавлено когда-то
|
||||
}
|
||||
public sealed class DefaultDebugService : DebugService
|
||||
{
|
||||
|
@ -66,7 +66,6 @@ namespace DCFApixels.DragonECS
|
||||
return AutoToString(self, typeof(T), isWriteName);
|
||||
}
|
||||
|
||||
//TODO сделать специальный вывод в виде названий констант для Enum-ов
|
||||
private static string AutoToString(object target, Type type, bool isWriteName)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
|
||||
|
@ -39,6 +39,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
private AddParams _defaultAddParams = new AddParams(BASIC_LAYER, 0, false);
|
||||
|
||||
private HashSet<Type> _uniqueSystemsSet = new HashSet<Type>();
|
||||
|
||||
#region Properties
|
||||
//private ReadOnlySpan<SystemNode> SystemRecords
|
||||
//{
|
||||
@ -107,10 +109,14 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
InsertAfterNode_Internal(_endIndex, system, layer, sortOrder, isUnique);
|
||||
}
|
||||
int _DEBUG_COUNTER = 0;
|
||||
private void InsertAfterNode_Internal(int insertAfterIndex, IEcsProcess system, string layer, int sortOrder, bool isUnique)
|
||||
{
|
||||
_DEBUG_COUNTER++;
|
||||
//TODO нужно потестить
|
||||
if (isUnique && _uniqueSystemsSet.Add(system.GetType()) == false)
|
||||
{
|
||||
EcsDebug.PrintWarning($"The pipeline already contains a unique instance of {system.GetType().Name}");
|
||||
}
|
||||
|
||||
SystemNode record = new SystemNode(system, layer, sortOrder, isUnique);
|
||||
int newIndex;
|
||||
if (_freeNodesCount <= 0)
|
||||
@ -175,10 +181,7 @@ namespace DCFApixels.DragonECS
|
||||
_defaultAddParams = oldDefaultAddParams;
|
||||
}
|
||||
|
||||
if (module is IInjectionUnit injectionUnit)
|
||||
{
|
||||
Injector.Inject(injectionUnit);
|
||||
}
|
||||
Injector.Inject(module);
|
||||
return this;
|
||||
}
|
||||
#endregion
|
||||
@ -251,6 +254,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public Builder Remove<TSystem>()
|
||||
{
|
||||
_uniqueSystemsSet.Remove(typeof(TSystem));
|
||||
|
||||
if (_systemNodesCount <= 1)
|
||||
{
|
||||
if (_systemNodesCount == 1 && _systemNodes[0].system is TSystem)
|
||||
@ -293,9 +298,6 @@ namespace DCFApixels.DragonECS
|
||||
_layerLists.Add(BASIC_LAYER, basicLayerList);
|
||||
}
|
||||
|
||||
//ERROR Уникальные системы ломают работу подсчета систем
|
||||
HashSet<Type> uniqueSystemsSet = new HashSet<Type>();
|
||||
|
||||
int allSystemsLength = 0;
|
||||
foreach (var item in _layerLists)
|
||||
{
|
||||
@ -320,10 +322,12 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
list = basicLayerList;
|
||||
}
|
||||
if (node.isUnique == false || uniqueSystemsSet.Add(node.system.GetType()))
|
||||
{
|
||||
list.Add(node.system, node.sortOrder, node.isUnique);
|
||||
}
|
||||
list.Add(node.system, node.sortOrder, node.isUnique);
|
||||
|
||||
//if (node.isUnique == false || uniqueSystemsSet.Add(node.system.GetType()))
|
||||
//{
|
||||
// list.Add(node.system, node.sortOrder, node.isUnique);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@ -525,15 +529,32 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
return InsertAfter(targetLayer, movingLayers);
|
||||
}
|
||||
|
||||
private static bool AreMatchingOrderIdentical(IReadOnlyList<string> listA, IReadOnlyList<string> listB)
|
||||
{
|
||||
int indexA = 0;
|
||||
foreach (string itemB in listB)
|
||||
{
|
||||
if (indexA < listA.Count && listA[indexA] == itemB)
|
||||
{
|
||||
indexA++;
|
||||
}
|
||||
}
|
||||
return indexA == listA.Count;
|
||||
}
|
||||
public void MergeWith(IReadOnlyList<string> other)
|
||||
{
|
||||
//TODO добавить оишбку если порядок совпадающих слоев не совпадает
|
||||
HashSet<string> seen = new HashSet<string>();
|
||||
List<string> result = new List<string>();
|
||||
|
||||
List<string> listA = _layers;
|
||||
IReadOnlyList<string> listB = other;
|
||||
|
||||
if (AreMatchingOrderIdentical(listA, listB) == false)
|
||||
{
|
||||
Throw.Exception("Для слияния списков слоев, нужно чтобы названия слоев, присутствующие в обоих списках, появлялись в одном и том же порядке в обоих списках");
|
||||
}
|
||||
|
||||
HashSet<string> seen = new HashSet<string>();
|
||||
List<string> result = new List<string>();
|
||||
|
||||
foreach (string item in listA)
|
||||
{
|
||||
seen.Add(item);
|
||||
|
@ -224,6 +224,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region EcsModule
|
||||
public interface IEcsModule
|
||||
{
|
||||
void Import(EcsPipeline.Builder b);
|
||||
@ -237,6 +238,7 @@ namespace DCFApixels.DragonECS
|
||||
void IInjectionUnit.InitInjectionNode(InjectionNodes nodes) { nodes.AddNode<T>(); }
|
||||
public EcsModule() { if (GetType() != typeof(T)) { Throw.UndefinedException(); } }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extensions
|
||||
public static partial class EcsPipelineExtensions
|
||||
|
@ -7,20 +7,18 @@ namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
private readonly Injector _source;
|
||||
private readonly Type _type;
|
||||
private InjectionNodeBase[] _nodes = new InjectionNodeBase[2];
|
||||
private InjectionNodeBase[] _nodes = new InjectionNodeBase[4];
|
||||
private int _nodesCount = 0;
|
||||
|
||||
private object _currentInjectedDependency;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _type; }
|
||||
}
|
||||
public object CurrentInjectedDependency
|
||||
public ReadOnlySpan<InjectionNodeBase> Nodes
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _currentInjectedDependency; }
|
||||
get { return new ReadOnlySpan<InjectionNodeBase>(_nodes, 0, _nodesCount); }
|
||||
}
|
||||
public InjectionBranch(Injector source, Type type)
|
||||
{
|
||||
@ -29,7 +27,6 @@ namespace DCFApixels.DragonECS.Internal
|
||||
}
|
||||
public void Inject(object obj)
|
||||
{
|
||||
_currentInjectedDependency = obj;
|
||||
for (int i = 0; i < _nodesCount; i++)
|
||||
{
|
||||
_nodes[i].Inject(obj);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -9,6 +10,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
get { return _type; }
|
||||
}
|
||||
public abstract object CurrentInjectedDependencyRaw { get; }
|
||||
protected InjectionNodeBase(Type type)
|
||||
{
|
||||
_type = type;
|
||||
@ -22,7 +24,18 @@ namespace DCFApixels.DragonECS.Internal
|
||||
internal sealed class InjectionNode<T> : InjectionNodeBase
|
||||
{
|
||||
private EcsProcess<IEcsInject<T>> _process;
|
||||
public InjectionNode(Type type) : base(type) { }
|
||||
private T _currentInjectedDependency;
|
||||
public sealed override object CurrentInjectedDependencyRaw
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _currentInjectedDependency; }
|
||||
}
|
||||
public T CurrentInjectedDependency
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _currentInjectedDependency; }
|
||||
}
|
||||
public InjectionNode() : base(typeof(T)) { }
|
||||
public sealed override void Init(EcsPipeline pipeline)
|
||||
{
|
||||
_process = pipeline.GetProcess<IEcsInject<T>>();
|
||||
@ -30,6 +43,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
public sealed override void Inject(object raw)
|
||||
{
|
||||
T obj = (T)raw;
|
||||
_currentInjectedDependency = obj;
|
||||
for (int i = 0; i < _process.Length; i++)
|
||||
{
|
||||
_process[i].Inject(obj);
|
||||
|
@ -1,6 +1,7 @@
|
||||
using DCFApixels.DragonECS.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
@ -12,6 +13,10 @@ namespace DCFApixels.DragonECS
|
||||
private Dictionary<Type, InjectionNodeBase> _nodes = new Dictionary<Type, InjectionNodeBase>(32);
|
||||
private bool _isInit = false;
|
||||
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
private HashSet<Type> _requiredInjectionTypes = new HashSet<Type>();
|
||||
#endif
|
||||
|
||||
public EcsPipeline Pipelie
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -24,43 +29,36 @@ namespace DCFApixels.DragonECS
|
||||
public void Inject<T>(T obj)
|
||||
{
|
||||
object raw = obj;
|
||||
Type type = obj.GetType();
|
||||
if (_branches.TryGetValue(type, out InjectionBranch branch) == false)
|
||||
Type tType = typeof(T);
|
||||
Type objType = obj.GetType();
|
||||
if (_branches.TryGetValue(objType, out InjectionBranch branch) == false)
|
||||
{
|
||||
if (typeof(T) == type)
|
||||
if (_nodes.ContainsKey(tType) == false)
|
||||
{
|
||||
if (_nodes.ContainsKey(type) == false)
|
||||
{
|
||||
InitNode(new InjectionNode<T>(type));
|
||||
}
|
||||
branch = new InjectionBranch(this, type);
|
||||
InitBranch(branch);
|
||||
InitNode(new InjectionNode<T>());
|
||||
}
|
||||
else
|
||||
bool hasNode = _nodes.ContainsKey(objType);
|
||||
if (hasNode == false && obj is IInjectionUnit unit)
|
||||
{
|
||||
bool hasNode = _nodes.ContainsKey(type);
|
||||
if (hasNode == false && obj is IInjectionUnit unit)
|
||||
{
|
||||
unit.InitInjectionNode(new InjectionNodes(this));
|
||||
hasNode = _nodes.ContainsKey(type);
|
||||
}
|
||||
if (hasNode)
|
||||
{
|
||||
branch = new InjectionBranch(this, type);
|
||||
InitBranch(branch);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO переработать это исключение
|
||||
// идея следующая, в режиме дебага с помощью рефлекшена собрать информацию о системах в которых есть IEcsInject, собрать все типы которые принимают системы,
|
||||
// потом при инициирующих инъекциях проверить что во все собранные типы были заинжектены. Если нет, то только тогда бросать исключение.
|
||||
// Исключения можно заранее определять и собирать, а бросать на моменте. Например тут создать исключение, и если инхекции небыло то бросить его.
|
||||
// Дополнительно обернуть все в #if DEBUG
|
||||
unit.InitInjectionNode(new InjectionNodes(this));
|
||||
hasNode = _nodes.ContainsKey(objType);
|
||||
}
|
||||
|
||||
//Другой вариант, тут добавить дополнительную проверку, если среди систем есть системы с IEcsInject<T> где T это obj.GetType() то бросить исключение
|
||||
throw new EcsInjectionException($"To create an injection branch, no injection node of {type.Name} was found. To create a node, use the AddNode<{type.Name}>() method directly in the injector or in the implementation of the IInjectionUnit for {type.Name}.");
|
||||
branch = new InjectionBranch(this, objType);
|
||||
InitBranch(branch);
|
||||
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
foreach (var requiredInjectionType in _requiredInjectionTypes)
|
||||
{
|
||||
if (requiredInjectionType.IsAssignableFrom(objType))
|
||||
{
|
||||
if (_nodes.ContainsKey(requiredInjectionType) == false)
|
||||
{
|
||||
throw new EcsInjectionException($"A systems in the pipeline implements IEcsInject<{requiredInjectionType.Name}> interface, but no suitable injection node was found in the Injector. To create a node, use Injector.AddNode<{requiredInjectionType.Name}>() or implement the IInjectionUnit interface for type {objType.Name}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
branch.Inject(raw);
|
||||
}
|
||||
@ -68,26 +66,19 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
return (T)Extract_Internal(typeof(T));
|
||||
}
|
||||
private object Extract_Internal(Type type)
|
||||
private object Extract_Internal(Type type)//TODO проверить
|
||||
{
|
||||
if (_branches.TryGetValue(type, out InjectionBranch branch))
|
||||
if (_nodes.TryGetValue(type, out InjectionNodeBase node))
|
||||
{
|
||||
return branch.CurrentInjectedDependency;
|
||||
return node.CurrentInjectedDependencyRaw;
|
||||
}
|
||||
return null;
|
||||
|
||||
//if (_nodes.ContainsKey(type))
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
//throw new EcsInjectionException($"The injection graph is missing a node for {type.Name} type. To create a node, use the AddNode<{type.Name}>() method directly in the injector or in the implementation of the IInjectionUnit for {type.Name}.");
|
||||
throw new EcsInjectionException($"The injection graph is missing a node for {type.Name} type. To create a node, use the Injector.AddNode<{type.Name}>() method directly in the injector or in the implementation of the IInjectionUnit for {type.Name}.");
|
||||
}
|
||||
public void AddNode<T>()
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (_nodes.ContainsKey(type) == false)
|
||||
if (_nodes.ContainsKey(typeof(T)) == false)
|
||||
{
|
||||
InitNode(new InjectionNode<T>(type));
|
||||
InitNode(new InjectionNode<T>());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -132,16 +123,27 @@ namespace DCFApixels.DragonECS
|
||||
#region Build
|
||||
private void Init(EcsPipeline pipeline)
|
||||
{
|
||||
if (_isInit)
|
||||
{
|
||||
throw new Exception("Already initialized");
|
||||
}
|
||||
if (_isInit) { Throw.Exception("Already initialized"); }
|
||||
|
||||
_pipeline = pipeline;
|
||||
foreach (var node in _nodes.Values)
|
||||
foreach (var pair in _nodes)
|
||||
{
|
||||
node.Init(pipeline);
|
||||
pair.Value.Init(pipeline);
|
||||
}
|
||||
_isInit = true;
|
||||
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
var systems = _pipeline.AllSystems;
|
||||
var injectType = typeof(IEcsInject<>);
|
||||
foreach (var system in systems)
|
||||
{
|
||||
var type = system.GetType();
|
||||
foreach (var requiredInjectionType in type.GetInterfaces().Where(o => o.IsGenericType && o.GetGenericTypeDefinition() == injectType).Select(o => o.GenericTypeArguments[0]))
|
||||
{
|
||||
_requiredInjectionTypes.Add(requiredInjectionType);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
private bool TryDeclare<T>()
|
||||
{
|
||||
@ -150,7 +152,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
return false;
|
||||
}
|
||||
InitNode(new InjectionNode<T>(type));
|
||||
InitNode(new InjectionNode<T>());
|
||||
#if !REFLECTION_DISABLED
|
||||
if (IsCanInstantiated(type))
|
||||
#endif
|
||||
@ -180,13 +182,13 @@ namespace DCFApixels.DragonECS
|
||||
_initInjections.Add(new InitInject<T>(obj));
|
||||
return _source;
|
||||
}
|
||||
public EcsPipeline.Builder Extract<T>(ref T obj)
|
||||
public EcsPipeline.Builder Extract<T>(ref T obj)//TODO проверить
|
||||
{
|
||||
Type type = typeof(T);
|
||||
for (int i = _initInjections.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var item = _initInjections[i];
|
||||
if (item.Type.IsAssignableFrom(type))
|
||||
if (type.IsAssignableFrom(item.Type))
|
||||
{
|
||||
obj = (T)item.Raw;
|
||||
return _source;
|
||||
|
@ -39,6 +39,6 @@
|
||||
}
|
||||
public interface IInjectionUnit
|
||||
{
|
||||
void InitInjectionNode(InjectionNodes nodes);
|
||||
void InitInjectionNode(InjectionNodes graph);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user