fix assignable types injection

This commit is contained in:
DCFApixels 2025-03-10 22:21:27 +08:00
parent 73c10e98ca
commit ae49f52272
2 changed files with 54 additions and 38 deletions

View File

@ -10,8 +10,8 @@ namespace DCFApixels.DragonECS
internal class AutoInjectionMap
{
private readonly EcsPipeline _source;
private Dictionary<Type, List<InjectedPropertyRecord>> _systemProperties;
private HashSet<Type> _notInjected;
private Dictionary<Type, List<InjectedPropertyRecord>> _systemProperties = new Dictionary<Type, List<InjectedPropertyRecord>>();
private HashSet<Type> _notInjected = new HashSet<Type>();
private bool _isDummyInjected = false;
private bool _isPreInitInjectionComplete = false;
@ -20,17 +20,16 @@ namespace DCFApixels.DragonECS
{
_source = source;
var allsystems = _source.AllSystems;
_systemProperties = new Dictionary<Type, List<InjectedPropertyRecord>>();
_notInjected = new HashSet<Type>();
foreach (var system in allsystems)
{
Type systemType = system.GetType();
if (systemType == typeof(AutoInjectSystem)) { continue; }
foreach (var property in GetAllPropertiesFor(systemType, isAgressiveInjection))
{
Type propertType = property.PropertyType;
List<InjectedPropertyRecord> list;
if (!_systemProperties.TryGetValue(propertType, out list))
if (_systemProperties.TryGetValue(propertType, out list) == false)
{
list = new List<InjectedPropertyRecord>();
_systemProperties.Add(propertType, list);
@ -43,17 +42,24 @@ namespace DCFApixels.DragonECS
}
}
}
private static void Do(Type type, List<IInjectedProperty> result, bool isAgressiveInjection)
private static List<IInjectedProperty> GetAllPropertiesFor(Type type, bool isAgressiveInjection)
{
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
result.AddRange(type.GetFields(bindingFlags)
.Where(o => isAgressiveInjection || o.GetCustomAttribute<DIAttribute>() != null)
List<IInjectedProperty> result = new List<IInjectedProperty>();
GetAllPropertiesFor(type, isAgressiveInjection, result);
return result;
}
private static void GetAllPropertiesFor(Type type, bool isAgressiveInjection, List<IInjectedProperty> result)
{
const BindingFlags REFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
result.AddRange(type.GetFields(REFL_FLAGS)
.Where(o => isAgressiveInjection || o.HasAttribute<DIAttribute>())
.Select(o => new InjectedField(o)));
result.AddRange(type.GetProperties(bindingFlags)
result.AddRange(type.GetProperties(REFL_FLAGS)
.Where(o =>
{
if (!isAgressiveInjection && o.GetCustomAttribute<DIAttribute>() == null)
if (!isAgressiveInjection && o.HasAttribute<DIAttribute>() == false)
{
return false;
}
@ -63,10 +69,11 @@ namespace DCFApixels.DragonECS
return o.CanWrite == false;
})
.Select(o => new InjectedProperty(o)));
result.AddRange(type.GetMethods(bindingFlags)
result.AddRange(type.GetMethods(REFL_FLAGS)
.Where(o =>
{
if (!isAgressiveInjection && o.GetCustomAttribute<DIAttribute>() == null)
if (!isAgressiveInjection && o.HasAttribute<DIAttribute>() == false)
{
return false;
}
@ -81,49 +88,53 @@ namespace DCFApixels.DragonECS
return o.IsGenericMethod == false && parameters.Length == 1;
})
.Select(o => new InjectedMethod(o)));
if (type.BaseType != null)
{
Do(type.BaseType, result, isAgressiveInjection);
GetAllPropertiesFor(type.BaseType, isAgressiveInjection, result);
}
}
private static List<IInjectedProperty> GetAllPropertiesFor(Type type, bool isAgressiveInjection)
{
List<IInjectedProperty> result = new List<IInjectedProperty>();
Do(type, result, isAgressiveInjection);
return result;
}
private Type[] _relatedTypesBuffer;
public void Inject(Type fieldType, object obj)
{
if (!_isPreInitInjectionComplete)
if (_isPreInitInjectionComplete == false)
{
_notInjected.Remove(fieldType);
}
if (_systemProperties.TryGetValue(fieldType, out List<InjectedPropertyRecord> list))
if (_relatedTypesBuffer == null || _relatedTypesBuffer.Length < _systemProperties.Count)
{
string name = string.Empty;
if (obj is INamedMember named)
_relatedTypesBuffer = new Type[_systemProperties.Count];
}
int relatedTypesCount = 0;
foreach (var pair in _systemProperties)
{
if (pair.Key == fieldType || pair.Key.IsAssignableFrom(fieldType))
{
name = named.Name;
_relatedTypesBuffer[relatedTypesCount++] = pair.Key;
}
foreach (var item in list)
}
foreach (var type in new ReadOnlySpan<Type>(_relatedTypesBuffer, 0, relatedTypesCount))
{
if (_systemProperties.TryGetValue(type, out List<InjectedPropertyRecord> list))
{
string propertyName = item.Attribute.NamedInjection;
if (string.IsNullOrEmpty(propertyName) || propertyName == name)
string name = string.Empty;
if (obj is INamedMember named)
{
item.property.Inject(item.target, obj);
name = named.Name;
}
foreach (var item in list)
{
string propertyName = item.Attribute.NamedInjection;
if (string.IsNullOrEmpty(propertyName) || propertyName == name)
{
item.property.Inject(item.target, obj);
}
}
}
}
Type baseType = fieldType.BaseType;
if (baseType != null)
{
Inject(baseType, obj);
}
}
public void InjectDummy()

View File

@ -18,5 +18,10 @@ namespace DCFApixels.DragonECS.AutoInjections.Internal
attribute = self.GetCustomAttribute<T>();
return attribute != null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasAttribute<T>(this MemberInfo self) where T : Attribute
{
return self.GetCustomAttribute<T>() != null;
}
}
}