Compare commits

..

No commits in common. "main" and "0.9.11" have entirely different histories.
main ... 0.9.11

16 changed files with 174 additions and 349 deletions

1
.gitignore vendored
View File

@ -35,7 +35,6 @@ ExportedObj/
*.csproj
*.unityproj
*.sln
*.sln.meta
*.suo
*.tmp
*.user

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Mikhail(DCFApixels)
Copyright (c) 2023 Mikhail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -11,35 +11,11 @@
# Auto Injections for [DragonECS](https://github.com/DCFApixels/DragonECS)
<table>
<tr></tr>
<tr>
<td colspan="3">Readme Languages:</td>
</tr>
<tr></tr>
<tr>
<td nowrap width="100">
<a href="https://github.com/DCFApixels/DragonECS-AutoInjections/blob/main/README-RU.md">
<img src="https://github.com/user-attachments/assets/3c699094-f8e6-471d-a7c1-6d2e9530e721"></br>
<span>Русский</span>
</a>
</td>
<td nowrap width="100">
<a href="https://github.com/DCFApixels/DragonECS-AutoInjections">
<img src="https://github.com/user-attachments/assets/30528cb5-f38e-49f0-b23e-d001844ae930"></br>
<span>English(WIP)</span>
</a>
</td>
</tr>
</table>
</br>
| Languages: | [Русский](https://github.com/DCFApixels/DragonECS-AutoInjections/blob/main/README-RU.md) | [English(WIP)](https://github.com/DCFApixels/DragonECS-AutoInjections) |
| :--- | :--- | :--- |
Расширение призвано сократить объем кода, упростив инъекцию зависимостей, делая их автоматически.
> [!WARNING]
> Проект в стадии разработки. API может меняться.
> **ВАЖНО!** Проект в стадии разработки. API может меняться.
# Оглавление
- [Установка](#установка)
- [Интеграция](#интеграция)
@ -61,7 +37,7 @@
Опционально:
+ Игровые движки с C#: Unity, Godot, MonoGame и т.д.
Протестировано:
Протестированно:
+ **Unity:** Минимальная версия 2020.1.0;
## Установка для Unity
@ -70,7 +46,7 @@
```
https://github.com/DCFApixels/DragonECS-AutoInjections.git
```
* ### В виде исходников
* ### В виде иходников
Фреймворк так же может быть добавлен в проект в виде исходников.
</br>
@ -145,7 +121,7 @@ sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomet
}
//...
// Если в пайплайн не был добавлен раннер, то GetRunnerAuto автоматически добавит экземпляр DoSomethingProcessRunner.
// Если в пайплайн небыл добавлен раннер, то GetRunnerAuto автоматически добавит экземпляр DoSomethingProcessRunner.
_pipeline.GetRunnerAuto<IDoSomethingProcess>().Do();
```
@ -214,7 +190,7 @@ class VelocitySystem : IEcsRun, IEcsInject<EcsDefaultWorld>, IEcsInject<TimeServ
# Не null инъекции
Чтобы поле помеченное `[EcsInject]` было проинициализированно даже в случае отстувия инъекции, в конструктор атрибута можно передать тип болванку. В примере ниже поле `foo` получит экземпляр класса `Foo` из инъекции или экземпляр `FooDummy : Foo` если инъекции не было.
Чтобы поле помеченное `[EcsInject]` было проинициализированно даже в случае отстувия инъекции, в конструктор атрибута можно передать тип болванку. В примере ниже поле `foo` получит экземпляр класса `Foo` из инъекции или экземпляр `FooDummy : Foo` если инъекции небыло.
``` csharp
[EcsInject(typeof(FooDummy))] Foo foo;
```

View File

@ -11,34 +11,11 @@
# Auto Injections for [DragonECS](https://github.com/DCFApixels/DragonECS)
<table>
<tr></tr>
<tr>
<td colspan="3">Readme Languages:</td>
</tr>
<tr></tr>
<tr>
<td nowrap width="100">
<a href="https://github.com/DCFApixels/DragonECS-AutoInjections/blob/main/README-RU.md">
<img src="https://github.com/user-attachments/assets/7bc29394-46d6-44a3-bace-0a3bae65d755"></br>
<span>Русский</span>
</a>
</td>
<td nowrap width="100">
<a href="https://github.com/DCFApixels/DragonECS-AutoInjections">
<img src="https://github.com/user-attachments/assets/3c699094-f8e6-471d-a7c1-6d2e9530e721"></br>
<span>English(WIP)</span>
</a>
</td>
</tr>
</table>
</br>
| Languages: | [Русский](https://github.com/DCFApixels/DragonECS-AutoInjections/blob/main/README-RU.md) | [English(WIP)](https://github.com/DCFApixels/DragonECS-AutoInjections) |
| :--- | :--- | :--- |
The extension is designed to reduce the amount of code by simplifying dependency injection by doing injections automatically.
> [!WARNING]
> The project is a work in progress, API may change.
>
> **NOTICE:** The project is a work in progress, API may change.
> While the English version of the README is incomplete, you can view the [Russian version](https://github.com/DCFApixels/DragonECS-AutoInjections/blob/main/README-RU.md).
@ -59,12 +36,12 @@ Tested with:
## Unity Installation
* ### Unity Package
The package can be installed as a Unity package by adding the Git URL [in the PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) or manually adding it to `Packages/manifest.json`:
The framework can be installed as a Unity package by adding the Git URL [in the PackageManager](https://docs.unity3d.com/2023.2/Documentation/Manual/upm-ui-giturl.html) or manually adding it to `Packages/manifest.json`:
```
https://github.com/DCFApixels/DragonECS-AutoInjections.git
```
* ### Source Code
The package can also be added to the project as source code.
The framework can also be added to the project as source code.
</br>

View File

@ -8,7 +8,7 @@
"displayName": "DragonECS-AutoInjections",
"description": "Auto Injections for DragonECS",
"unity": "2020.3",
"version": "0.9.18",
"version": "0.9.11",
"repository": {
"type": "git",
"url": "https://github.com/DCFApixels/DragonECS-AutoInjections.git"

View File

@ -1,10 +1,5 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using DCFApixels.DragonECS.AutoInjections.Internal;
using DCFApixels.DragonECS.AutoInjections.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace DCFApixels.DragonECS
@ -13,7 +8,7 @@ namespace DCFApixels.DragonECS
{
protected sealed override void Init(Builder b)
{
//EcsAspectAutoHelper.Fill(this, b);
EcsAspectAutoHelper.Fill(this, b);
InitAfterDI(b);
}
protected virtual void InitAfterDI(Builder b) { }
@ -21,119 +16,90 @@ namespace DCFApixels.DragonECS
internal static class EcsAspectAutoHelper
{
private static readonly MethodInfo _incluedMethod;
private static readonly MethodInfo _excludeMethod;
private static readonly MethodInfo _optionalMethod;
private static readonly MethodInfo _combineMethod;
private const BindingFlags REFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
static EcsAspectAutoHelper()
public static void Fill(EcsAspect s, EcsAspect.Builder b)
{
Type builderType = typeof(EcsAspect.Builder);
Type builderType = b.GetType();
MethodInfo incluedMethod = builderType.GetMethod("IncludePool", BindingFlags.Instance | BindingFlags.Public);
MethodInfo excludeMethod = builderType.GetMethod("ExcludePool", BindingFlags.Instance | BindingFlags.Public);
MethodInfo optionalMethod = builderType.GetMethod("OptionalPool", BindingFlags.Instance | BindingFlags.Public);
MethodInfo includeImplicitMethod = builderType.GetMethod("IncludeImplicit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo excludeImplicitMethod = builderType.GetMethod("ExcludeImplicit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo combineMethod = builderType.GetMethod("Combine", BindingFlags.Instance | BindingFlags.Public);
_incluedMethod = builderType.GetMethod("IncludePool", REFL_FLAGS);
_excludeMethod = builderType.GetMethod("ExcludePool", REFL_FLAGS);
_optionalMethod = builderType.GetMethod("OptionalPool", REFL_FLAGS);
_combineMethod = builderType.GetMethod("Combine", REFL_FLAGS);
}
public static void FillMaskFields(object aspect, EcsMask mask)
Type aspectType = s.GetType();
foreach (var attribute in aspectType.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
{
foreach (FieldInfo fieldInfo in aspect.GetType().GetFields(REFL_FLAGS))
{
if (fieldInfo.GetCustomAttribute<MaskAttribute>() == null)
if (attribute is IncImplicitAttribute incImplicit)
{
if (incImplicit.isPool)
incluedMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
else
includeImplicitMethod.Invoke(b, new object[] { incImplicit.type });
continue;
}
if (fieldInfo.FieldType == typeof(EcsMask))
if (attribute is ExcImplicitAttribute excImplicit)
{
fieldInfo.SetValue(aspect, mask);
if (excImplicit.isPool)
excludeMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
else
excludeImplicitMethod.Invoke(b, new object[] { excImplicit.type });
continue;
}
else if (fieldInfo.FieldType == typeof(EcsStaticMask))
{
fieldInfo.SetValue(aspect, mask.ToStatic());
}
}
}
public static void FillFields(object aspect, EcsAspect.Builder builder)
{
Type aspectType = aspect.GetType();
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
var implicitInjectAttributes = (IEnumerable<ImplicitInjectAttribute>)aspectType.GetCustomAttributes<ImplicitInjectAttribute>();
FieldInfo[] fieldInfos = aspectType.GetFields(REFL_FLAGS);
FieldInfo[] fieldInfos = aspectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fieldInfos)
{
Type fieldType = fieldInfo.FieldType;
implicitInjectAttributes = implicitInjectAttributes.Concat(fieldInfo.GetCustomAttributes<ImplicitInjectAttribute>());
foreach (var attribute in fieldInfo.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
{
if (attribute is IncImplicitAttribute incImplicit)
{
if (incImplicit.isPool)
incluedMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
else
includeImplicitMethod.Invoke(b, new object[] { incImplicit.type });
continue;
}
if (attribute is ExcImplicitAttribute excImplicit)
{
if (excImplicit.isPool)
excludeMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
else
excludeImplicitMethod.Invoke(b, new object[] { excImplicit.type });
continue;
}
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
if (fieldInfo.TryGetCustomAttribute(out InjectAspectMemberAttribute injectAttribute) == false)
if (!fieldInfo.TryGetCustomAttribute(out InjectAspectMemberAttribute injectAttribute))
{
continue;
}
IEcsPool pool;
switch (injectAttribute)
{
case IncAttribute incAtr:
if (builder.World.TryFindPoolInstance(fieldType, out pool))
{
builder.SetMaskInclude(fieldType);
fieldInfo.SetValue(aspect, pool);
}
else
{
pool = (IEcsPool)_incluedMethod.MakeGenericMethod(fieldType).Invoke(builder, null);
}
fieldInfo.SetValue(aspect, pool);
break;
case ExcAttribute extAtr:
if (builder.World.TryFindPoolInstance(fieldType, out pool))
{
builder.SetMaskExclude(fieldType);
fieldInfo.SetValue(aspect, pool);
}
else
{
pool = (IEcsPool)_excludeMethod.MakeGenericMethod(fieldType).Invoke(builder, null);
}
fieldInfo.SetValue(aspect, pool);
break;
case OptAttribute optAtr:
if (builder.World.TryFindPoolInstance(fieldType, out pool))
{
fieldInfo.SetValue(aspect, pool);
}
else
{
pool = (IEcsPool)_optionalMethod.MakeGenericMethod(fieldType).Invoke(builder, null);
}
fieldInfo.SetValue(aspect, pool);
break;
case CombineAttribute combineAtr:
pool = builder.World.FindPoolInstance(fieldType);
fieldInfo.SetValue(aspect, _combineMethod.MakeGenericMethod(fieldType).Invoke(builder, new object[] { combineAtr.Order }));
break;
default:
break;
}
}
foreach (var attribute in implicitInjectAttributes)
if (injectAttribute is IncAttribute)
{
if (attribute is IncImplicitAttribute incImplicitAtr)
{
builder.SetMaskInclude(incImplicitAtr.ComponentType);
fieldInfo.SetValue(s, incluedMethod.MakeGenericMethod(fieldType).Invoke(b, null));
continue;
}
if (attribute is ExcImplicitAttribute excImplicitAtr)
if (injectAttribute is ExcAttribute)
{
builder.SetMaskExclude(excImplicitAtr.ComponentType);
fieldInfo.SetValue(s, excludeMethod.MakeGenericMethod(fieldType).Invoke(b, null));
continue;
}
if (injectAttribute is OptAttribute)
{
fieldInfo.SetValue(s, optionalMethod.MakeGenericMethod(fieldType).Invoke(b, null));
continue;
}
if (injectAttribute is CombineAttribute combAttribute)
{
fieldInfo.SetValue(s, combineMethod.MakeGenericMethod(fieldType).Invoke(b, new object[] { combAttribute.order }));
continue;
}
}
}
}
}

View File

@ -1,7 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using DCFApixels.DragonECS.PoolsCore;
using DCFApixels.DragonECS.PoolsCore;
using System;
using System.Linq;
@ -17,30 +14,32 @@ namespace DCFApixels.DragonECS
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class CombineAttribute : InjectAspectMemberAttribute
{
public readonly int Order = 0;
public CombineAttribute(int order = 0) { Order = order; }
public readonly int order = 0;
public CombineAttribute(int order = 0) { this.order = order; }
}
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class MaskAttribute : InjectAspectMemberAttribute { }
public abstract class ImplicitInjectAttribute : Attribute
{
public readonly Type ComponentType;
public ImplicitInjectAttribute(Type componentType)
{
ComponentType = componentType;
}
}
public abstract class ImplicitInjectAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class IncImplicitAttribute : ImplicitInjectAttribute
{
public IncImplicitAttribute(Type type) : base(type) { }
public readonly Type type;
public readonly bool isPool;
public IncImplicitAttribute(Type type)
{
this.type = type;
isPool = type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation));
}
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class ExcImplicitAttribute : ImplicitInjectAttribute
{
public ExcImplicitAttribute(Type type) : base(type) { }
public readonly Type type;
public readonly bool isPool;
public ExcImplicitAttribute(Type type)
{
this.type = type;
isPool = type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation));
}
}
}

View File

@ -1,37 +1,16 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System;
namespace DCFApixels.DragonECS
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class DIAttribute : Attribute
public sealed class EcsInjectAttribute : Attribute
{
public static readonly DIAttribute Dummy = new DIAttribute();
public readonly Type NotNullDummyType = null;
public readonly string NamedInjection = string.Empty;
public DIAttribute() { }
public DIAttribute(string namedInjection)
public static readonly EcsInjectAttribute Dummy = new EcsInjectAttribute(null);
public readonly Type notNullDummyType;
public EcsInjectAttribute(Type notNullDummyType = null)
{
NamedInjection = namedInjection;
this.notNullDummyType = notNullDummyType;
}
public DIAttribute(Type notNullDummyType)
{
NotNullDummyType = notNullDummyType;
}
public DIAttribute(string namedInjection, Type notNullDummyType)
{
NamedInjection = namedInjection;
NotNullDummyType = notNullDummyType;
}
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
[Obsolete("Use DI attribute")]
public sealed class EcsInjectAttribute : DIAttribute
{
public EcsInjectAttribute(Type notNullDummyType = null) : base(notNullDummyType) { }
}
}

View File

@ -1,6 +1,3 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using DCFApixels.DragonECS.AutoInjections;
using DCFApixels.DragonECS.AutoInjections.Internal;
using System;
@ -13,8 +10,8 @@ namespace DCFApixels.DragonECS
internal class AutoInjectionMap
{
private readonly EcsPipeline _source;
private Dictionary<Type, List<InjectedPropertyRecord>> _injectedTypeToPropertiesMap = new Dictionary<Type, List<InjectedPropertyRecord>>();
private HashSet<Type> _notInjected = new HashSet<Type>();
private Dictionary<Type, List<InjectedPropertyRecord>> _systemProperties;
private HashSet<Type> _notInjected;
private bool _isDummyInjected = false;
private bool _isPreInitInjectionComplete = false;
@ -23,122 +20,109 @@ 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 (_injectedTypeToPropertiesMap.TryGetValue(propertType, out list) == false)
if (!_systemProperties.TryGetValue(propertType, out list))
{
list = new List<InjectedPropertyRecord>();
_injectedTypeToPropertiesMap.Add(propertType, list);
_systemProperties.Add(propertType, list);
}
list.Add(new InjectedPropertyRecord(system, property));
if (property.GetAutoInjectAttribute() != DIAttribute.Dummy)
if (property.GetAutoInjectAttribute() != EcsInjectAttribute.Dummy)
{
_notInjected.Add(propertType);
}
}
}
//foreach (var pair in _systemProperties)
//{
// _notInjected.Add(pair.Key);
//}
}
private static List<IInjectedProperty> GetAllPropertiesFor(Type type, bool isAgressiveInjection)
{
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>())
//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;
result.AddRange(type.GetFields(bindingFlags)
.Where(o => isAgressiveInjection || o.GetCustomAttribute<EcsInjectAttribute>() != null)
.Select(o => new InjectedField(o)));
result.AddRange(type.GetProperties(REFL_FLAGS)
result.AddRange(type.GetProperties(bindingFlags)
.Where(o =>
{
if (!isAgressiveInjection && o.HasAttribute<DIAttribute>() == false)
if (!isAgressiveInjection && o.GetCustomAttribute<EcsInjectAttribute>() == null)
{
return false;
}
#if DEBUG
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!isAgressiveInjection && o.CanWrite == false) { Throw.PropertyIsCantWrite(o); }
#endif
return o.CanWrite;
return o.CanWrite == false;
})
.Select(o => new InjectedProperty(o)));
result.AddRange(type.GetMethods(REFL_FLAGS)
result.AddRange(type.GetMethods(bindingFlags)
.Where(o =>
{
if (!isAgressiveInjection && o.HasAttribute<DIAttribute>() == false)
if (!isAgressiveInjection && o.GetCustomAttribute<EcsInjectAttribute>() == null)
{
return false;
}
var parameters = o.GetParameters();
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!isAgressiveInjection)
{
#if DEBUG
if (o.IsGenericMethod) { Throw.MethodIsGeneric(o); }
if (parameters.Length != 1) { Throw.MethodArgumentsGreater1(o); }
#endif
}
#endif
return o.IsGenericMethod == false && parameters.Length == 1;
})
.Select(o => new InjectedMethod(o)));
if (type.BaseType != null)
{
GetAllPropertiesFor(type.BaseType, isAgressiveInjection, result);
Do(type.BaseType, result, isAgressiveInjection);
}
}
private Type[] _relatedTypesBuffer;
private static List<IInjectedProperty> GetAllPropertiesFor(Type type, bool isAgressiveInjection)
{
List<IInjectedProperty> result = new List<IInjectedProperty>();
Do(type, result, isAgressiveInjection);
return result;
}
public void Inject(Type fieldType, object obj)
{
if (_relatedTypesBuffer == null || _relatedTypesBuffer.Length < _injectedTypeToPropertiesMap.Count)
if (!_isPreInitInjectionComplete)
{
_relatedTypesBuffer = new Type[_injectedTypeToPropertiesMap.Count];
}
int relatedTypesCount = 0;
foreach (var pair in _injectedTypeToPropertiesMap)
{
if (pair.Key == fieldType || pair.Key.IsAssignableFrom(fieldType))
{
_relatedTypesBuffer[relatedTypesCount++] = pair.Key;
}
_notInjected.Remove(fieldType);
}
foreach (var type in new ReadOnlySpan<Type>(_relatedTypesBuffer, 0, relatedTypesCount))
if (_systemProperties.TryGetValue(fieldType, out List<InjectedPropertyRecord> list))
{
if (_injectedTypeToPropertiesMap.TryGetValue(type, out List<InjectedPropertyRecord> list))
{
string name = string.Empty;
if (obj is INamedMember named)
{
name = named.Name;
}
foreach (var item in list)
{
string propertyName = item.Attribute.NamedInjection;
if (string.IsNullOrEmpty(propertyName) || propertyName == name)
{
if (_isPreInitInjectionComplete == false)
{
_notInjected.Remove(item.property.PropertyType);
}
item.property.Inject(item.target, obj);
}
}
}
}
Type baseType = fieldType.BaseType;
if (baseType != null)
{
Inject(baseType, obj);
}
}
public void InjectDummy()
@ -148,18 +132,18 @@ namespace DCFApixels.DragonECS
_isDummyInjected = true;
foreach (var notInjectedItem in _notInjected)
{
foreach (var systemRecord in _injectedTypeToPropertiesMap[notInjectedItem])
foreach (var systemRecord in _systemProperties[notInjectedItem])
{
if (systemRecord.Attribute.NotNullDummyType == null)
if (systemRecord.Attribute.notNullDummyType == null)
continue;
if (systemRecord.property.IsInjected)
continue;
if (systemRecord.property.PropertyType.IsAssignableFrom(systemRecord.Attribute.NotNullDummyType) == false)
if (systemRecord.property.PropertyType.IsAssignableFrom(systemRecord.Attribute.notNullDummyType) == false)
{
EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, $"The {systemRecord.Attribute.NotNullDummyType} dummy cannot be assigned to the {systemRecord.property.PropertyType.Name} field");
EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, $"The {systemRecord.Attribute.notNullDummyType} dummy cannot be assigned to the {systemRecord.property.PropertyType.Name} field");
continue;
}
systemRecord.property.Inject(systemRecord.target, DummyInstance.GetInstance(systemRecord.Attribute.NotNullDummyType));
systemRecord.property.Inject(systemRecord.target, DummyInstance.GetInstance(systemRecord.Attribute.notNullDummyType));
}
}
WarningMissedInjections();
@ -172,7 +156,7 @@ namespace DCFApixels.DragonECS
#if DEBUG
foreach (var item in _notInjected)
{
foreach (var systemRecord in _injectedTypeToPropertiesMap[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)}.");
}
@ -189,7 +173,7 @@ namespace DCFApixels.DragonECS
{
public readonly IEcsProcess target;
public readonly IInjectedProperty property;
public DIAttribute Attribute { get { return property.GetAutoInjectAttribute(); } }
public EcsInjectAttribute Attribute { get { return property.GetAutoInjectAttribute(); } }
public InjectedPropertyRecord(IEcsProcess target, IInjectedProperty property)
{
this.target = target;
@ -202,33 +186,15 @@ namespace DCFApixels.DragonECS
[MetaColor(MetaColor.Gray)]
[MetaGroup(EcsAutoInjectionsConsts.PACK_GROUP, EcsConsts.DI_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "The system responsible for the processing of automatic injections. The .AutoInject() method adds an AutoInjectSystem to the systems pipelines.")]
public class AutoInjectSystem : IEcsInject<object>, IEcsPipelineMember, IOnInitInjectionComplete, IEcsDefaultAddParams
public class AutoInjectSystem : IEcsInject<object>, IEcsPipelineMember, IOnInitInjectionComplete
{
public AddParams AddParams => new AddParams(layerName: EcsConsts.PRE_BEGIN_LAYER, isUnique: true);
private EcsPipeline _pipeline;
EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; }
private List<object> _delayedInjects = new List<object>();
private AutoInjectionMap _autoInjectionMap;
private bool _isInitInjectionCompleted;
private bool _isAgressiveInjection;
static AutoInjectSystem()
{
EcsAspect.OnInit -= EcsAspect_OnInit;
EcsAspect.OnInit += EcsAspect_OnInit;
EcsAspect.OnAfterInit -= EcsAspect_OnBuild;
EcsAspect.OnAfterInit += EcsAspect_OnBuild;
}
private static void EcsAspect_OnInit(object aspect, EcsAspect.Builder builder)
{
EcsAspectAutoHelper.FillFields(aspect, builder);
}
private static void EcsAspect_OnBuild(object aspect, EcsMask mask)
{
EcsAspectAutoHelper.FillMaskFields(aspect, mask);
}
public AutoInjectSystem(bool isAgressiveInjection = false)
{
_isAgressiveInjection = isAgressiveInjection;
@ -246,7 +212,6 @@ namespace DCFApixels.DragonECS
}
}
public void OnBeforeInitInjection() { }
public void OnInitInjectionComplete()
{
_autoInjectionMap = new AutoInjectionMap(_pipeline, _isAgressiveInjection);
@ -263,8 +228,6 @@ namespace DCFApixels.DragonECS
_delayedInjects = null;
GC.Collect(0);
}
EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; }
}
#region Utils
@ -272,22 +235,22 @@ namespace DCFApixels.DragonECS
{
bool IsInjected { get; }
Type PropertyType { get; }
DIAttribute GetAutoInjectAttribute();
EcsInjectAttribute GetAutoInjectAttribute();
void Inject(object target, object value);
}
internal class InjectedField : IInjectedProperty
{
private FieldInfo _member;
private DIAttribute _injectAttribute;
private EcsInjectAttribute _injectAttribute;
public bool IsInjected { get; private set; }
public Type PropertyType { get { return _member.FieldType; } }
public InjectedField(FieldInfo member)
{
_member = member;
_injectAttribute = member.GetCustomAttribute<DIAttribute>();
if (_injectAttribute == null) { _injectAttribute = DIAttribute.Dummy; }
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
}
public DIAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public void Inject(object target, object value)
{
_member.SetValue(target, value);
@ -297,16 +260,16 @@ namespace DCFApixels.DragonECS
internal class InjectedProperty : IInjectedProperty
{
private PropertyInfo _member;
private DIAttribute _injectAttribute;
private EcsInjectAttribute _injectAttribute;
public bool IsInjected { get; private set; }
public Type PropertyType { get { return _member.PropertyType; } }
public InjectedProperty(PropertyInfo member)
{
_member = member;
_injectAttribute = member.GetCustomAttribute<DIAttribute>();
if (_injectAttribute == null) { _injectAttribute = DIAttribute.Dummy; }
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
}
public DIAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public void Inject(object target, object value)
{
_member.SetValue(target, value);
@ -316,18 +279,18 @@ namespace DCFApixels.DragonECS
internal class InjectedMethod : IInjectedProperty
{
private MethodInfo _member;
private DIAttribute _injectAttribute;
private EcsInjectAttribute _injectAttribute;
private Type propertyType;
public bool IsInjected { get; private set; }
public Type PropertyType { get { return propertyType; } }
public InjectedMethod(MethodInfo member)
{
_member = member;
_injectAttribute = member.GetCustomAttribute<DIAttribute>();
_injectAttribute = member.GetCustomAttribute<EcsInjectAttribute>();
propertyType = _member.GetParameters()[0].ParameterType;
if (_injectAttribute == null) { _injectAttribute = DIAttribute.Dummy; }
if (_injectAttribute == null) { _injectAttribute = EcsInjectAttribute.Dummy; }
}
public DIAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public EcsInjectAttribute GetAutoInjectAttribute() { return _injectAttribute; }
public void Inject(object target, object value)
{
_member.Invoke(target, new object[] { value });

View File

@ -1,23 +1,10 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
namespace DCFApixels.DragonECS
namespace DCFApixels.DragonECS
{
public static class AutoInjectSystemExtensions
{
[MetaColor(MetaColor.DragonCyan)]
public class AutoInjectModule : IEcsModule
{
public bool isAgressiveInjection;
public void Import(EcsPipeline.Builder b)
{
b.AddUnique(new AutoInjectSystem(isAgressiveInjection));
}
}
public static EcsPipeline.Builder AutoInject(this EcsPipeline.Builder self, bool isAgressiveInjection = false)
{
self.AddUnique(new AutoInjectSystem(isAgressiveInjection));
self.Add(new AutoInjectSystem(isAgressiveInjection));
return self;
}
}

View File

@ -1,8 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System;
[AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
public sealed class BindWithRunnerAttribute : Attribute
{

View File

@ -1,7 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using DCFApixels.DragonECS.AutoInjections.Internal;
using DCFApixels.DragonECS.AutoInjections.Internal;
using System;
using System.Reflection;

View File

@ -1,7 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System;
using System.Reflection;
namespace DCFApixels.DragonECS

View File

@ -1,7 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;

View File

@ -1,7 +1,4 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
using System;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
@ -21,10 +18,5 @@ 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;
}
}
}