mirror of
https://github.com/DCFApixels/DragonECS-AutoInjections.git
synced 2025-09-17 20:34:34 +08:00
add agresive injections
This commit is contained in:
parent
64dcda0157
commit
b7ab56b645
@ -5,8 +5,8 @@ namespace DCFApixels.DragonECS
|
|||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||||
public sealed class EcsInjectAttribute : Attribute
|
public sealed class EcsInjectAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
public static readonly EcsInjectAttribute Dummy = new EcsInjectAttribute(null);
|
||||||
public readonly Type notNullDummyType;
|
public readonly Type notNullDummyType;
|
||||||
|
|
||||||
public EcsInjectAttribute(Type notNullDummyType = null)
|
public EcsInjectAttribute(Type notNullDummyType = null)
|
||||||
{
|
{
|
||||||
this.notNullDummyType = notNullDummyType;
|
this.notNullDummyType = notNullDummyType;
|
||||||
|
@ -9,102 +9,129 @@ namespace DCFApixels.DragonECS
|
|||||||
internal class AutoInjectionMap
|
internal class AutoInjectionMap
|
||||||
{
|
{
|
||||||
private readonly EcsPipeline _source;
|
private readonly EcsPipeline _source;
|
||||||
private Dictionary<Type, List<InjectedPropertyRecord>> _systemProoperties;
|
private Dictionary<Type, List<InjectedPropertyRecord>> _systemProperties;
|
||||||
private HashSet<Type> _notInjected;
|
private HashSet<Type> _notInjected;
|
||||||
private bool _isDummyInjected = false;
|
private bool _isDummyInjected = false;
|
||||||
|
|
||||||
private bool _isPreInitInjectionComplete = false;
|
private bool _isPreInitInjectionComplete = false;
|
||||||
|
|
||||||
public AutoInjectionMap(EcsPipeline source)
|
public AutoInjectionMap(EcsPipeline source, bool isAgressiveInjection = false)
|
||||||
{
|
{
|
||||||
_source = source;
|
_source = source;
|
||||||
var allsystems = _source.AllSystems;
|
var allsystems = _source.AllSystems;
|
||||||
_systemProoperties = new Dictionary<Type, List<InjectedPropertyRecord>>();
|
_systemProperties = new Dictionary<Type, List<InjectedPropertyRecord>>();
|
||||||
_notInjected = new HashSet<Type>();
|
_notInjected = new HashSet<Type>();
|
||||||
foreach (var system in allsystems)
|
foreach (var system in allsystems)
|
||||||
{
|
{
|
||||||
Type systemType = system.GetType();
|
Type systemType = system.GetType();
|
||||||
foreach (var property in GetAllPropertiesFor(systemType))
|
if (systemType == typeof(AutoInjectSystem)) { continue; }
|
||||||
|
foreach (var property in GetAllPropertiesFor(systemType, isAgressiveInjection))
|
||||||
{
|
{
|
||||||
Type fieldType = property.PropertyType;
|
Type propertType = property.PropertyType;
|
||||||
List<InjectedPropertyRecord> list;
|
List<InjectedPropertyRecord> list;
|
||||||
if (!_systemProoperties.TryGetValue(fieldType, out list))
|
if (!_systemProperties.TryGetValue(propertType, out list))
|
||||||
{
|
{
|
||||||
list = new List<InjectedPropertyRecord>();
|
list = new List<InjectedPropertyRecord>();
|
||||||
_systemProoperties.Add(fieldType, list);
|
_systemProperties.Add(propertType, list);
|
||||||
}
|
}
|
||||||
list.Add(new InjectedPropertyRecord(system, property));
|
list.Add(new InjectedPropertyRecord(system, property));
|
||||||
}
|
if (property.GetAutoInjectAttribute() != EcsInjectAttribute.Dummy)
|
||||||
}
|
|
||||||
foreach (var item in _systemProoperties.Keys)
|
|
||||||
{
|
{
|
||||||
_notInjected.Add(item);
|
_notInjected.Add(propertType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//foreach (var pair in _systemProperties)
|
||||||
|
//{
|
||||||
|
// _notInjected.Add(pair.Key);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
private static void Do(Type type, List<IInjectedProperty> result)
|
//private bool IsInjectTarget(MemberInfo member)
|
||||||
|
//{
|
||||||
|
// return _isAgressiveInjection || member.GetCustomAttribute<EcsInjectAttribute>() != null;
|
||||||
|
//}
|
||||||
|
private static void Do(Type type, List<IInjectedProperty> result, bool isAgressiveInjection)
|
||||||
{
|
{
|
||||||
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
result.AddRange(type.GetFields(bindingFlags)
|
result.AddRange(type.GetFields(bindingFlags)
|
||||||
.Where(o => o.GetCustomAttribute<EcsInjectAttribute>() != null)
|
.Where(o => isAgressiveInjection || o.GetCustomAttribute<EcsInjectAttribute>() != null)
|
||||||
.Select(o => new InjectedField(o)));
|
.Select(o => new InjectedField(o)));
|
||||||
result.AddRange(type.GetProperties(bindingFlags)
|
result.AddRange(type.GetProperties(bindingFlags)
|
||||||
.Where(o =>
|
.Where(o =>
|
||||||
{
|
{
|
||||||
if (o.GetCustomAttribute<EcsInjectAttribute>() == null)
|
if (!isAgressiveInjection && o.GetCustomAttribute<EcsInjectAttribute>() == null)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (o.CanWrite == false) Throw.PropertyIsCantWrite(o);
|
if (!isAgressiveInjection && o.CanWrite == false) { Throw.PropertyIsCantWrite(o); }
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return o.CanWrite == false;
|
||||||
})
|
})
|
||||||
.Select(o => new InjectedProperty(o)));
|
.Select(o => new InjectedProperty(o)));
|
||||||
result.AddRange(type.GetMethods(bindingFlags)
|
result.AddRange(type.GetMethods(bindingFlags)
|
||||||
.Where(o =>
|
.Where(o =>
|
||||||
{
|
{
|
||||||
if (o.GetCustomAttribute<EcsInjectAttribute>() == null)
|
if (!isAgressiveInjection && o.GetCustomAttribute<EcsInjectAttribute>() == null)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
var parameters = o.GetParameters();
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (o.IsGenericMethod) Throw.MethodIsGeneric(o);
|
if (!isAgressiveInjection)
|
||||||
if (o.GetParameters().Length != 1) Throw.MethodArgumentsGreater1(o);
|
{
|
||||||
|
if (o.IsGenericMethod) { Throw.MethodIsGeneric(o); }
|
||||||
|
if (parameters.Length != 1) { Throw.MethodArgumentsGreater1(o); }
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return o.IsGenericMethod == false && parameters.Length == 1;
|
||||||
})
|
})
|
||||||
.Select(o => new InjectedMethod(o)));
|
.Select(o => new InjectedMethod(o)));
|
||||||
if (type.BaseType != null)
|
if (type.BaseType != null)
|
||||||
Do(type.BaseType, result);
|
{
|
||||||
|
Do(type.BaseType, result, isAgressiveInjection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<IInjectedProperty> GetAllPropertiesFor(Type type)
|
private static List<IInjectedProperty> GetAllPropertiesFor(Type type, bool isAgressiveInjection)
|
||||||
{
|
{
|
||||||
List<IInjectedProperty> result = new List<IInjectedProperty>();
|
List<IInjectedProperty> result = new List<IInjectedProperty>();
|
||||||
Do(type, result);
|
Do(type, result, isAgressiveInjection);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public void Inject(Type fieldType, object obj)
|
public void Inject(Type fieldType, object obj)
|
||||||
{
|
{
|
||||||
if (!_isPreInitInjectionComplete)
|
if (!_isPreInitInjectionComplete)
|
||||||
|
{
|
||||||
_notInjected.Remove(fieldType);
|
_notInjected.Remove(fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_systemProperties.TryGetValue(fieldType, out List<InjectedPropertyRecord> list))
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
item.property.Inject(item.target, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Type baseType = fieldType.BaseType;
|
Type baseType = fieldType.BaseType;
|
||||||
if (baseType != null)
|
if (baseType != null)
|
||||||
Inject(baseType, obj);
|
|
||||||
|
|
||||||
if (_systemProoperties.TryGetValue(fieldType, out List<InjectedPropertyRecord> list))
|
|
||||||
{
|
{
|
||||||
foreach (var item in list)
|
Inject(baseType, obj);
|
||||||
item.property.Inject(item.target, obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InjectDummy()
|
public void InjectDummy()
|
||||||
{
|
{
|
||||||
if (_isDummyInjected)
|
if (_isDummyInjected) { return; }
|
||||||
return;
|
|
||||||
_isDummyInjected = true;
|
_isDummyInjected = true;
|
||||||
foreach (var notInjectedItem in _notInjected)
|
foreach (var notInjectedItem in _notInjected)
|
||||||
{
|
{
|
||||||
foreach (var systemRecord in _systemProoperties[notInjectedItem])
|
foreach (var systemRecord in _systemProperties[notInjectedItem])
|
||||||
{
|
{
|
||||||
if (systemRecord.Attribute.notNullDummyType == null)
|
if (systemRecord.Attribute.notNullDummyType == null)
|
||||||
continue;
|
continue;
|
||||||
@ -128,9 +155,11 @@ namespace DCFApixels.DragonECS
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
foreach (var item in _notInjected)
|
foreach (var item in _notInjected)
|
||||||
{
|
{
|
||||||
foreach (var systemRecord in _systemProoperties[item])
|
foreach (var systemRecord in _systemProperties[item])
|
||||||
|
{
|
||||||
EcsDebug.PrintWarning($"in system {EcsDebugUtility.GetGenericTypeFullName(systemRecord.target.GetType(), 1)} is missing an injection of {EcsDebugUtility.GetGenericTypeFullName(item, 1)}.");
|
EcsDebug.PrintWarning($"in system {EcsDebugUtility.GetGenericTypeFullName(systemRecord.target.GetType(), 1)} is missing an injection of {EcsDebugUtility.GetGenericTypeFullName(item, 1)}.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +172,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public readonly IEcsProcess target;
|
public readonly IEcsProcess target;
|
||||||
public readonly IInjectedProperty property;
|
public readonly IInjectedProperty property;
|
||||||
public EcsInjectAttribute Attribute => property.GetAutoInjectAttribute();
|
public EcsInjectAttribute Attribute { get { return property.GetAutoInjectAttribute(); } }
|
||||||
public InjectedPropertyRecord(IEcsProcess target, IInjectedProperty property)
|
public InjectedPropertyRecord(IEcsProcess target, IInjectedProperty property)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
@ -159,10 +188,16 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
private EcsPipeline _pipeline;
|
private EcsPipeline _pipeline;
|
||||||
EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; }
|
EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; }
|
||||||
|
|
||||||
private List<object> _delayedInjects = new List<object>();
|
private List<object> _delayedInjects = new List<object>();
|
||||||
private AutoInjectionMap _autoInjectionMap;
|
private AutoInjectionMap _autoInjectionMap;
|
||||||
private bool _isInitInjectionCompleted;
|
private bool _isInitInjectionCompleted;
|
||||||
|
private bool _isAgressiveInjection;
|
||||||
|
|
||||||
|
public AutoInjectSystem(bool isAgressiveInjection = false)
|
||||||
|
{
|
||||||
|
_isAgressiveInjection = isAgressiveInjection;
|
||||||
|
}
|
||||||
|
|
||||||
public void Inject(object obj)
|
public void Inject(object obj)
|
||||||
{
|
{
|
||||||
if (_isInitInjectionCompleted)
|
if (_isInitInjectionCompleted)
|
||||||
@ -177,7 +212,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
public void OnInitInjectionComplete()
|
public void OnInitInjectionComplete()
|
||||||
{
|
{
|
||||||
_autoInjectionMap = new AutoInjectionMap(_pipeline);
|
_autoInjectionMap = new AutoInjectionMap(_pipeline, _isAgressiveInjection);
|
||||||
_isInitInjectionCompleted = true;
|
_isInitInjectionCompleted = true;
|
||||||
|
|
||||||
foreach (var obj in _delayedInjects)
|
foreach (var obj in _delayedInjects)
|
||||||
@ -211,8 +246,9 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_member = member;
|
_member = member;
|
||||||
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
||||||
|
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
|
||||||
}
|
}
|
||||||
public EcsInjectAttribute GetAutoInjectAttribute() => _injectAttribute;
|
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
|
||||||
public void Inject(object target, object value)
|
public void Inject(object target, object value)
|
||||||
{
|
{
|
||||||
_member.SetValue(target, value);
|
_member.SetValue(target, value);
|
||||||
@ -229,8 +265,9 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
_member = member;
|
_member = member;
|
||||||
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
||||||
|
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
|
||||||
}
|
}
|
||||||
public EcsInjectAttribute GetAutoInjectAttribute() => _injectAttribute;
|
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
|
||||||
public void Inject(object target, object value)
|
public void Inject(object target, object value)
|
||||||
{
|
{
|
||||||
_member.SetValue(target, value);
|
_member.SetValue(target, value);
|
||||||
@ -249,8 +286,9 @@ namespace DCFApixels.DragonECS
|
|||||||
_member = member;
|
_member = member;
|
||||||
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
|
||||||
propertyType = _member.GetParameters()[0].ParameterType;
|
propertyType = _member.GetParameters()[0].ParameterType;
|
||||||
|
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
|
||||||
}
|
}
|
||||||
public EcsInjectAttribute GetAutoInjectAttribute() => _injectAttribute;
|
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
|
||||||
public void Inject(object target, object value)
|
public void Inject(object target, object value)
|
||||||
{
|
{
|
||||||
_member.Invoke(target, new object[] { value });
|
_member.Invoke(target, new object[] { value });
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
{
|
{
|
||||||
public static class AutoInjectSystemExtensions
|
public static class AutoInjectSystemExtensions
|
||||||
{
|
{
|
||||||
public static EcsPipeline.Builder AutoInject(this EcsPipeline.Builder self)
|
public static EcsPipeline.Builder AutoInject(this EcsPipeline.Builder self, bool isAgressiveInjection = false)
|
||||||
{
|
{
|
||||||
self.Add(new AutoInjectSystem());
|
self.Add(new AutoInjectSystem(isAgressiveInjection));
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user