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

View File

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