mirror of
https://github.com/DCFApixels/DragonECS-AutoInjections.git
synced 2025-09-17 20:34:34 +08:00
update the aspect auto-build
This commit is contained in:
parent
ae49f52272
commit
1b2cf99a68
@ -1,5 +1,7 @@
|
|||||||
using DCFApixels.DragonECS.AutoInjections.Internal;
|
using DCFApixels.DragonECS.AutoInjections.Internal;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
@ -8,7 +10,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
protected sealed override void Init(Builder b)
|
protected sealed override void Init(Builder b)
|
||||||
{
|
{
|
||||||
EcsAspectAutoHelper.Fill(this, b);
|
//EcsAspectAutoHelper.Fill(this, b);
|
||||||
InitAfterDI(b);
|
InitAfterDI(b);
|
||||||
}
|
}
|
||||||
protected virtual void InitAfterDI(Builder b) { }
|
protected virtual void InitAfterDI(Builder b) { }
|
||||||
@ -16,90 +18,117 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
internal static class EcsAspectAutoHelper
|
internal static class EcsAspectAutoHelper
|
||||||
{
|
{
|
||||||
public static void Fill(EcsAspect s, EcsAspect.Builder b)
|
private static readonly MethodInfo _incluedMethod;
|
||||||
|
private static readonly MethodInfo _excludeMethod;
|
||||||
|
private static readonly MethodInfo _optionalMethod;
|
||||||
|
private static readonly MethodInfo _includeImplicitMethod;
|
||||||
|
private static readonly MethodInfo _excludeImplicitMethod;
|
||||||
|
private static readonly MethodInfo _combineMethod;
|
||||||
|
static EcsAspectAutoHelper()
|
||||||
{
|
{
|
||||||
Type builderType = b.GetType();
|
const BindingFlags REFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
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);
|
|
||||||
|
|
||||||
Type aspectType = s.GetType();
|
Type builderType = typeof(EcsAspect.Builder);
|
||||||
|
|
||||||
foreach (var attribute in aspectType.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
|
_incluedMethod = builderType.GetMethod("IncludePool", REFL_FLAGS);
|
||||||
|
_excludeMethod = builderType.GetMethod("ExcludePool", REFL_FLAGS);
|
||||||
|
_optionalMethod = builderType.GetMethod("OptionalPool", REFL_FLAGS);
|
||||||
|
_includeImplicitMethod = builderType.GetMethod("IncludeImplicit", REFL_FLAGS);
|
||||||
|
_excludeImplicitMethod = builderType.GetMethod("ExcludeImplicit", REFL_FLAGS);
|
||||||
|
_combineMethod = builderType.GetMethod("Combine", REFL_FLAGS);
|
||||||
|
}
|
||||||
|
public static void FillMaskFields(object aspect, EcsMask mask)
|
||||||
{
|
{
|
||||||
if (attribute is IncImplicitAttribute incImplicit)
|
const BindingFlags REFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
|
foreach (FieldInfo fieldInfo in aspect.GetType().GetFields(REFL_FLAGS))
|
||||||
|
{
|
||||||
|
if (fieldInfo.GetCustomAttribute<MaskAttribute>() == null)
|
||||||
{
|
{
|
||||||
if (incImplicit.isPool)
|
|
||||||
incluedMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
|
|
||||||
else
|
|
||||||
includeImplicitMethod.Invoke(b, new object[] { incImplicit.type });
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attribute is ExcImplicitAttribute excImplicit)
|
|
||||||
|
if (fieldInfo.FieldType == typeof(EcsMask))
|
||||||
{
|
{
|
||||||
if (excImplicit.isPool)
|
fieldInfo.SetValue(aspect, mask);
|
||||||
excludeMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
|
|
||||||
else
|
|
||||||
excludeImplicitMethod.Invoke(b, new object[] { excImplicit.type });
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
|
else if (fieldInfo.FieldType == typeof(EcsStaticMask))
|
||||||
|
{
|
||||||
|
fieldInfo.SetValue(aspect, mask.ToStatic());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void FillFields(object aspect, EcsAspect.Builder builder)
|
||||||
|
{
|
||||||
|
const BindingFlags REFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
|
||||||
|
|
||||||
FieldInfo[] fieldInfos = aspectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
Type aspectType = aspect.GetType();
|
||||||
|
|
||||||
|
var implicitInjectAttributes = (IEnumerable<ImplicitInjectAttribute>)aspectType.GetCustomAttributes<ImplicitInjectAttribute>();
|
||||||
|
|
||||||
|
FieldInfo[] fieldInfos = aspectType.GetFields(REFL_FLAGS);
|
||||||
foreach (FieldInfo fieldInfo in fieldInfos)
|
foreach (FieldInfo fieldInfo in fieldInfos)
|
||||||
{
|
{
|
||||||
Type fieldType = fieldInfo.FieldType;
|
Type fieldType = fieldInfo.FieldType;
|
||||||
|
|
||||||
foreach (var attribute in fieldInfo.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
|
implicitInjectAttributes = implicitInjectAttributes.Concat(fieldInfo.GetCustomAttributes<ImplicitInjectAttribute>());
|
||||||
|
|
||||||
|
if (fieldInfo.TryGetCustomAttribute(out InjectAspectMemberAttribute injectAttribute) == false)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (injectAttribute)
|
||||||
|
{
|
||||||
|
case IncAttribute atr:
|
||||||
|
var x1 = _incluedMethod;
|
||||||
|
fieldInfo.SetValue(aspect, _incluedMethod.MakeGenericMethod(fieldType).Invoke(builder, null));
|
||||||
|
break;
|
||||||
|
case ExcAttribute atr:
|
||||||
|
var x2 = _excludeMethod;
|
||||||
|
fieldInfo.SetValue(aspect, _excludeMethod.MakeGenericMethod(fieldType).Invoke(builder, null));
|
||||||
|
break;
|
||||||
|
case OptAttribute atr:
|
||||||
|
var x3 = _optionalMethod;
|
||||||
|
fieldInfo.SetValue(aspect, _optionalMethod.MakeGenericMethod(fieldType).Invoke(builder, null));
|
||||||
|
break;
|
||||||
|
case CombineAttribute atr:
|
||||||
|
var x4 = _combineMethod;
|
||||||
|
fieldInfo.SetValue(aspect, _combineMethod.MakeGenericMethod(fieldType).Invoke(builder, new object[] { atr.Order }));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Inject(ImplicitInjectAttribute atr_, MethodInfo method_, MethodInfo implicitMethod_)
|
||||||
|
{
|
||||||
|
if (atr_.IsPool)
|
||||||
|
{
|
||||||
|
method_.MakeGenericMethod(atr_.Type).Invoke(builder, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
implicitMethod_.Invoke(builder, new object[] { atr_.Type });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var attribute in implicitInjectAttributes)
|
||||||
{
|
{
|
||||||
if (attribute is IncImplicitAttribute incImplicit)
|
if (attribute is IncImplicitAttribute incImplicit)
|
||||||
{
|
{
|
||||||
if (incImplicit.isPool)
|
Inject(incImplicit, _incluedMethod, _includeImplicitMethod);
|
||||||
incluedMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
|
|
||||||
else
|
|
||||||
includeImplicitMethod.Invoke(b, new object[] { incImplicit.type });
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (attribute is ExcImplicitAttribute excImplicit)
|
if (attribute is ExcImplicitAttribute excImplicit)
|
||||||
{
|
{
|
||||||
if (excImplicit.isPool)
|
Inject(excImplicit, _excludeMethod, _excludeImplicitMethod);
|
||||||
excludeMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
|
|
||||||
else
|
|
||||||
excludeImplicitMethod.Invoke(b, new object[] { excImplicit.type });
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
|
|
||||||
|
|
||||||
if (!fieldInfo.TryGetCustomAttribute(out InjectAspectMemberAttribute injectAttribute))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (injectAttribute is IncAttribute)
|
|
||||||
{
|
|
||||||
fieldInfo.SetValue(s, incluedMethod.MakeGenericMethod(fieldType).Invoke(b, null));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (injectAttribute is ExcAttribute)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,32 +14,32 @@ namespace DCFApixels.DragonECS
|
|||||||
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
|
||||||
public sealed class CombineAttribute : InjectAspectMemberAttribute
|
public sealed class CombineAttribute : InjectAspectMemberAttribute
|
||||||
{
|
{
|
||||||
public readonly int order = 0;
|
public readonly int Order = 0;
|
||||||
public CombineAttribute(int order = 0) { this.order = order; }
|
public CombineAttribute(int order = 0) { Order = order; }
|
||||||
}
|
}
|
||||||
|
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
|
||||||
|
public sealed class MaskAttribute : InjectAspectMemberAttribute { }
|
||||||
|
|
||||||
public abstract class ImplicitInjectAttribute : Attribute { }
|
|
||||||
|
public abstract class ImplicitInjectAttribute : Attribute
|
||||||
|
{
|
||||||
|
public readonly Type Type;
|
||||||
|
public readonly bool IsPool;
|
||||||
|
public ImplicitInjectAttribute(Type type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
IsPool = type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation));
|
||||||
|
}
|
||||||
|
}
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
|
||||||
public sealed class IncImplicitAttribute : ImplicitInjectAttribute
|
public sealed class IncImplicitAttribute : ImplicitInjectAttribute
|
||||||
{
|
{
|
||||||
public readonly Type type;
|
public IncImplicitAttribute(Type type) : base(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)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
|
||||||
public sealed class ExcImplicitAttribute : ImplicitInjectAttribute
|
public sealed class ExcImplicitAttribute : ImplicitInjectAttribute
|
||||||
{
|
{
|
||||||
public readonly Type type;
|
public ExcImplicitAttribute(Type type) : base(type) { }
|
||||||
public readonly bool isPool;
|
|
||||||
public ExcImplicitAttribute(Type type)
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
isPool = type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,15 +198,31 @@ namespace DCFApixels.DragonECS
|
|||||||
[MetaColor(MetaColor.Gray)]
|
[MetaColor(MetaColor.Gray)]
|
||||||
[MetaGroup(EcsAutoInjectionsConsts.PACK_GROUP, EcsConsts.DI_GROUP)]
|
[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.")]
|
[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
|
public class AutoInjectSystem : IEcsInject<object>, IEcsPipelineMember, IOnInitInjectionComplete, IEcsDefaultAddParams
|
||||||
{
|
{
|
||||||
|
public AddParams AddParams => new AddParams(layerName: EcsConsts.PRE_BEGIN_LAYER, isUnique: true);
|
||||||
|
|
||||||
private EcsPipeline _pipeline;
|
private EcsPipeline _pipeline;
|
||||||
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;
|
private bool _isAgressiveInjection;
|
||||||
|
|
||||||
|
static AutoInjectSystem()
|
||||||
|
{
|
||||||
|
EcsAspect.OnInit += EcsAspect_OnInit;
|
||||||
|
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)
|
public AutoInjectSystem(bool isAgressiveInjection = false)
|
||||||
{
|
{
|
||||||
_isAgressiveInjection = isAgressiveInjection;
|
_isAgressiveInjection = isAgressiveInjection;
|
||||||
@ -224,6 +240,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnBeforeInitInjection() { }
|
||||||
public void OnInitInjectionComplete()
|
public void OnInitInjectionComplete()
|
||||||
{
|
{
|
||||||
_autoInjectionMap = new AutoInjectionMap(_pipeline, _isAgressiveInjection);
|
_autoInjectionMap = new AutoInjectionMap(_pipeline, _isAgressiveInjection);
|
||||||
@ -240,6 +257,8 @@ namespace DCFApixels.DragonECS
|
|||||||
_delayedInjects = null;
|
_delayedInjects = null;
|
||||||
GC.Collect(0);
|
GC.Collect(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EcsPipeline IEcsPipelineMember.Pipeline { get => _pipeline; set => _pipeline = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Utils
|
#region Utils
|
||||||
|
Loading…
Reference in New Issue
Block a user