diff --git a/src/Attributes/InjectionAttributes.cs b/src/Attributes/InjectionAttributes.cs index 1ca7db3..f834d16 100644 --- a/src/Attributes/InjectionAttributes.cs +++ b/src/Attributes/InjectionAttributes.cs @@ -5,8 +5,8 @@ namespace DCFApixels.DragonECS [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)] public sealed class EcsInjectAttribute : Attribute { + public static readonly EcsInjectAttribute Dummy = new EcsInjectAttribute(null); public readonly Type notNullDummyType; - public EcsInjectAttribute(Type notNullDummyType = null) { this.notNullDummyType = notNullDummyType; diff --git a/src/AutoInjectSystem.cs b/src/AutoInjectSystem.cs index 6f62f35..acee697 100644 --- a/src/AutoInjectSystem.cs +++ b/src/AutoInjectSystem.cs @@ -9,102 +9,129 @@ namespace DCFApixels.DragonECS internal class AutoInjectionMap { private readonly EcsPipeline _source; - private Dictionary> _systemProoperties; + private Dictionary> _systemProperties; private HashSet _notInjected; private bool _isDummyInjected = false; private bool _isPreInitInjectionComplete = false; - public AutoInjectionMap(EcsPipeline source) + public AutoInjectionMap(EcsPipeline source, bool isAgressiveInjection = false) { _source = source; var allsystems = _source.AllSystems; - _systemProoperties = new Dictionary>(); + _systemProperties = new Dictionary>(); _notInjected = new HashSet(); foreach (var system in allsystems) { 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 list; - if (!_systemProoperties.TryGetValue(fieldType, out list)) + if (!_systemProperties.TryGetValue(propertType, out list)) { list = new List(); - _systemProoperties.Add(fieldType, list); + _systemProperties.Add(propertType, list); } list.Add(new InjectedPropertyRecord(system, property)); + if (property.GetAutoInjectAttribute() != EcsInjectAttribute.Dummy) + { + _notInjected.Add(propertType); + } } } - foreach (var item in _systemProoperties.Keys) - { - _notInjected.Add(item); - } + //foreach (var pair in _systemProperties) + //{ + // _notInjected.Add(pair.Key); + //} } - private static void Do(Type type, List result) + //private bool IsInjectTarget(MemberInfo member) + //{ + // return _isAgressiveInjection || member.GetCustomAttribute() != null; + //} + private static void Do(Type type, List result, bool isAgressiveInjection) { const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; result.AddRange(type.GetFields(bindingFlags) - .Where(o => o.GetCustomAttribute() != null) + .Where(o => isAgressiveInjection || o.GetCustomAttribute() != null) .Select(o => new InjectedField(o))); result.AddRange(type.GetProperties(bindingFlags) .Where(o => { - if (o.GetCustomAttribute() == null) + if (!isAgressiveInjection && o.GetCustomAttribute() == null) + { return false; + } #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (o.CanWrite == false) Throw.PropertyIsCantWrite(o); + if (!isAgressiveInjection && o.CanWrite == false) { Throw.PropertyIsCantWrite(o); } #endif - return true; + return o.CanWrite == false; }) .Select(o => new InjectedProperty(o))); result.AddRange(type.GetMethods(bindingFlags) .Where(o => { - if (o.GetCustomAttribute() == null) + if (!isAgressiveInjection && o.GetCustomAttribute() == null) + { return false; + } + var parameters = o.GetParameters(); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (o.IsGenericMethod) Throw.MethodIsGeneric(o); - if (o.GetParameters().Length != 1) Throw.MethodArgumentsGreater1(o); + if (!isAgressiveInjection) + { + if (o.IsGenericMethod) { Throw.MethodIsGeneric(o); } + if (parameters.Length != 1) { Throw.MethodArgumentsGreater1(o); } + } #endif - return true; + return o.IsGenericMethod == false && parameters.Length == 1; }) .Select(o => new InjectedMethod(o))); if (type.BaseType != null) - Do(type.BaseType, result); + { + Do(type.BaseType, result, isAgressiveInjection); + } } - private static List GetAllPropertiesFor(Type type) + private static List GetAllPropertiesFor(Type type, bool isAgressiveInjection) { List result = new List(); - Do(type, result); + Do(type, result, isAgressiveInjection); return result; } public void Inject(Type fieldType, object obj) { if (!_isPreInitInjectionComplete) + { _notInjected.Remove(fieldType); + } + + if (_systemProperties.TryGetValue(fieldType, out List list)) + { + foreach (var item in list) + { + item.property.Inject(item.target, obj); + } + } + + Type baseType = fieldType.BaseType; if (baseType != null) - Inject(baseType, obj); - - if (_systemProoperties.TryGetValue(fieldType, out List list)) { - foreach (var item in list) - item.property.Inject(item.target, obj); + Inject(baseType, obj); } } public void InjectDummy() { - if (_isDummyInjected) - return; + if (_isDummyInjected) { return; } + _isDummyInjected = true; foreach (var notInjectedItem in _notInjected) { - foreach (var systemRecord in _systemProoperties[notInjectedItem]) + foreach (var systemRecord in _systemProperties[notInjectedItem]) { if (systemRecord.Attribute.notNullDummyType == null) continue; @@ -128,8 +155,10 @@ namespace DCFApixels.DragonECS #if DEBUG 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)}."); + } } #endif } @@ -143,7 +172,7 @@ namespace DCFApixels.DragonECS { public readonly IEcsProcess target; public readonly IInjectedProperty property; - public EcsInjectAttribute Attribute => property.GetAutoInjectAttribute(); + public EcsInjectAttribute Attribute { get { return property.GetAutoInjectAttribute(); } } public InjectedPropertyRecord(IEcsProcess target, IInjectedProperty property) { this.target = target; @@ -159,10 +188,16 @@ namespace DCFApixels.DragonECS { private EcsPipeline _pipeline; EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; } - private List _delayedInjects = new List(); private AutoInjectionMap _autoInjectionMap; private bool _isInitInjectionCompleted; + private bool _isAgressiveInjection; + + public AutoInjectSystem(bool isAgressiveInjection = false) + { + _isAgressiveInjection = isAgressiveInjection; + } + public void Inject(object obj) { if (_isInitInjectionCompleted) @@ -177,7 +212,7 @@ namespace DCFApixels.DragonECS public void OnInitInjectionComplete() { - _autoInjectionMap = new AutoInjectionMap(_pipeline); + _autoInjectionMap = new AutoInjectionMap(_pipeline, _isAgressiveInjection); _isInitInjectionCompleted = true; foreach (var obj in _delayedInjects) @@ -211,8 +246,9 @@ namespace DCFApixels.DragonECS { _member = member; _injectAttribute = member.GetCustomAttribute(); + if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; } } - public EcsInjectAttribute GetAutoInjectAttribute() => _injectAttribute; + public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; } public void Inject(object target, object value) { _member.SetValue(target, value); @@ -229,8 +265,9 @@ namespace DCFApixels.DragonECS { _member = member; _injectAttribute = member.GetCustomAttribute(); + if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; } } - public EcsInjectAttribute GetAutoInjectAttribute() => _injectAttribute; + public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; } public void Inject(object target, object value) { _member.SetValue(target, value); @@ -249,8 +286,9 @@ namespace DCFApixels.DragonECS _member = member; _injectAttribute = member.GetCustomAttribute(); 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) { _member.Invoke(target, new object[] { value }); diff --git a/src/AutoInjectSystemExtensions.cs b/src/AutoInjectSystemExtensions.cs index 3733f71..db68806 100644 --- a/src/AutoInjectSystemExtensions.cs +++ b/src/AutoInjectSystemExtensions.cs @@ -2,9 +2,9 @@ { 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; } }