add notnull dummy

This commit is contained in:
Mikhail 2023-04-05 09:14:42 +08:00
parent 540d341778
commit 1a2bd2bea2
2 changed files with 72 additions and 7 deletions

View File

@ -5,7 +5,12 @@ namespace DCFApixels.DragonECS
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class AutoInjectAttribute : Attribute public sealed class AutoInjectAttribute : Attribute
{ {
public readonly Type notNullDummyType;
public AutoInjectAttribute(Type notNullDummyType = null)
{
this.notNullDummyType = notNullDummyType;
}
} }
} }

View File

@ -4,25 +4,35 @@ using System.Reflection;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
internal static class DummyInstance<T>
{
public static T intsance = (T)Activator.CreateInstance(typeof(T));
}
internal class AutoInjectionMap internal class AutoInjectionMap
{ {
private readonly EcsPipeline _source; private readonly EcsPipeline _source;
private Dictionary<Type, List<FiledRecord>> _systems; private Dictionary<Type, List<FiledRecord>> _systems;
private HashSet<Type> _notInjected;
private Type dummyInstance = typeof(DummyInstance<>);
private bool _isDummyInjected = false;
public AutoInjectionMap(EcsPipeline source) public AutoInjectionMap(EcsPipeline source)
{ {
_source = source; _source = source;
var allsystems = _source.AllSystems; var allsystems = _source.AllSystems;
_systems = new Dictionary<Type, List<FiledRecord>>(); _systems = new Dictionary<Type, List<FiledRecord>>();
_notInjected = new HashSet<Type>();
foreach (var system in allsystems) foreach (var system in allsystems)
{ {
Type systemType = system.GetType(); Type systemType = system.GetType();
foreach (var field in systemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) foreach (var field in systemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{ {
if(field.GetCustomAttribute<AutoInjectAttribute>() != null) AutoInjectAttribute autoInjectAttribute = field.GetCustomAttribute<AutoInjectAttribute>();
if (autoInjectAttribute != null)
{ {
Type fieldType = field.FieldType; Type fieldType = field.FieldType;
List<FiledRecord> list; List<FiledRecord> list;
if (!_systems.TryGetValue(fieldType, out list)) if (!_systems.TryGetValue(fieldType, out list))
@ -31,16 +41,19 @@ namespace DCFApixels.DragonECS
_systems.Add(fieldType, list); _systems.Add(fieldType, list);
} }
list.Add(new FiledRecord(system, field)); list.Add(new FiledRecord(system, field, autoInjectAttribute));
} }
} }
} }
foreach (var item in _systems.Keys)
{
_notInjected.Add(item);
}
} }
public void Inject(object obj) public void Inject(object obj)
{ {
_notInjected.Remove(obj.GetType());
Type objectType = obj.GetType(); Type objectType = obj.GetType();
if(_systems.TryGetValue(objectType, out List<FiledRecord> list)) if(_systems.TryGetValue(objectType, out List<FiledRecord> list))
{ {
@ -51,26 +64,59 @@ namespace DCFApixels.DragonECS
} }
} }
public void InjectDummy()
{
if (_isDummyInjected)
return;
_isDummyInjected = true;
foreach (var notInjectedItem in _notInjected)
{
foreach (var systemRecord in _systems[notInjectedItem])
{
if (systemRecord.attribute.notNullDummyType == null)
continue;
if (systemRecord.field.GetValue(systemRecord.target) != null)
continue;
if (systemRecord.field.FieldType.IsAssignableFrom(systemRecord.attribute.notNullDummyType) == false)
{
EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, $"The {systemRecord.attribute.notNullDummyType} dummy cannot be assigned to the {systemRecord.field.FieldType.Name} field");
continue;
}
systemRecord.field.SetValue(systemRecord.target,
dummyInstance.MakeGenericType(systemRecord.attribute.notNullDummyType).GetField("intsance", BindingFlags.Static | BindingFlags.Public).GetValue(null));
}
}
_notInjected.Clear();
_notInjected= null;
}
private readonly struct FiledRecord private readonly struct FiledRecord
{ {
public readonly IEcsSystem target; public readonly IEcsSystem target;
public readonly FieldInfo field; public readonly FieldInfo field;
public FiledRecord(IEcsSystem target, FieldInfo field) public readonly AutoInjectAttribute attribute;
public FiledRecord(IEcsSystem target, FieldInfo field, AutoInjectAttribute attribute)
{ {
this.target = target; this.target = target;
this.field = field; this.field = field;
this.attribute = attribute;
} }
} }
} }
[DebugHide, DebugColor(DebugColor.Gray)] [DebugHide, DebugColor(DebugColor.Gray)]
public class AutoInjectSystem : IEcsPreInitSystem, IEcsPreInject public class AutoInjectSystem : IEcsPreInitSystem, IEcsPreInject, IEcsPreInitInjectCallbacks
{ {
private EcsPipeline _pipeline; private EcsPipeline _pipeline;
private List<object> _injectQueue = new List<object>(); private List<object> _injectQueue = new List<object>();
private AutoInjectionMap _autoInjectionMap; private AutoInjectionMap _autoInjectionMap;
private bool _isPreInjectionComplete = false;
public void PreInject(object obj) public void PreInject(object obj)
{ {
if(_pipeline == null) if(_pipeline == null)
@ -91,11 +137,25 @@ namespace DCFApixels.DragonECS
} }
_injectQueue.Clear(); _injectQueue.Clear();
_injectQueue = null; _injectQueue = null;
if (_isPreInjectionComplete)
{
_autoInjectionMap.InjectDummy();
}
} }
private void AutoInject(object obj) private void AutoInject(object obj)
{ {
_autoInjectionMap.Inject(obj); _autoInjectionMap.Inject(obj);
} }
public void OnPreInitInjectionBefore() { }
public void OnPreInitInjectionAfter()
{
_isPreInjectionComplete = true;
if (_autoInjectionMap != null)
{
_autoInjectionMap.InjectDummy();
}
}
} }
} }