This commit is contained in:
Mikhail 2023-05-07 00:50:23 +08:00
parent 765373ea4b
commit 0a66736274
5 changed files with 148 additions and 64 deletions

View File

@ -3,11 +3,11 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class AutoInjectAttribute : Attribute public sealed class EcsInjectAttribute : Attribute
{ {
public readonly Type notNullDummyType; public readonly Type notNullDummyType;
public AutoInjectAttribute(Type notNullDummyType = null) public EcsInjectAttribute(Type notNullDummyType = null)
{ {
this.notNullDummyType = notNullDummyType; this.notNullDummyType = notNullDummyType;
} }

View File

@ -1,12 +1,56 @@
using System; using System;
using System.Linq;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public class InjectAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class IncAttribute : Attribute { } public sealed class IncAttribute : InjectAttribute { }
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class ExcAttribute : Attribute { } public sealed class ExcAttribute : InjectAttribute { }
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class OptAttribute : Attribute { } public sealed class OptAttribute : InjectAttribute { }
public abstract class ImplicitInjectAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class IncImplicitAttribute : ImplicitInjectAttribute
{
public readonly Type type;
public readonly bool isPool;
public IncImplicitAttribute(Type type)
{
if (type.IsValueType && !type.IsPrimitive)
{
isPool = false;
this.type = type;
return;
}
if (!type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation)))
throw new ArgumentException("Можно использовать только пулы наследованные от IEcsPoolImplementation<T>");
this.type = type;
isPool = true;
}
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public sealed class ExcImplicitAttribute : ImplicitInjectAttribute
{
public readonly Type type;
public readonly bool isPool;
public ExcImplicitAttribute(Type type)
{
if (type.IsValueType && !type.IsPrimitive)
{
isPool = false;
this.type = type;
return;
}
if (!type.GetInterfaces().Any(o => o == typeof(IEcsPoolImplementation)))
throw new ArgumentException("Можно использовать только пулы наследованные от IEcsPoolImplementation<T>");
this.type = type;
isPool = true;
}
}
} }

View File

@ -30,7 +30,7 @@ namespace DCFApixels.DragonECS
Type systemType = system.GetType(); Type systemType = system.GetType();
foreach (var field in systemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) foreach (var field in systemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{ {
AutoInjectAttribute autoInjectAttribute = field.GetCustomAttribute<AutoInjectAttribute>(); EcsInjectAttribute autoInjectAttribute = field.GetCustomAttribute<EcsInjectAttribute>();
if (autoInjectAttribute != null) if (autoInjectAttribute != null)
{ {
Type fieldType = field.FieldType; Type fieldType = field.FieldType;
@ -97,8 +97,8 @@ namespace DCFApixels.DragonECS
{ {
public readonly IEcsSystem target; public readonly IEcsSystem target;
public readonly FieldInfo field; public readonly FieldInfo field;
public readonly AutoInjectAttribute attribute; public readonly EcsInjectAttribute attribute;
public FiledRecord(IEcsSystem target, FieldInfo field, AutoInjectAttribute attribute) public FiledRecord(IEcsSystem target, FieldInfo field, EcsInjectAttribute attribute)
{ {
this.target = target; this.target = target;
this.field = field; this.field = field;
@ -108,7 +108,7 @@ namespace DCFApixels.DragonECS
} }
[DebugHide, DebugColor(DebugColor.Gray)] [DebugHide, DebugColor(DebugColor.Gray)]
public class AutoInjectSystem : IEcsPreInitSystem, IEcsPreInject, IEcsPreInitInjectCallbacks public class AutoInjectSystem : IEcsPreInitProcess, IEcsPreInject, IEcsPreInitInjectProcess
{ {
private EcsPipeline _pipeline; private EcsPipeline _pipeline;
private List<object> _injectQueue = new List<object>(); private List<object> _injectQueue = new List<object>();

View File

@ -1,55 +0,0 @@
using System;
using System.Reflection;
namespace DCFApixels.DragonECS
{
public abstract class EcsJoinAttachQueryDI<TAttachComponent> : EcsJoinAttachQuery<TAttachComponent>
where TAttachComponent : struct, IEcsAttachComponent
{
protected override void Init(Builder b) => EcsQueryDIHelper.Fill(this, b);
}
public abstract class EcsQueryDI : EcsQuery
{
protected override void Init(Builder b) => EcsQueryDIHelper.Fill(this, b);
}
internal static class EcsQueryDIHelper
{
public static void Fill(EcsQueryBase q, EcsQueryBase.Builder b)
{
Type builderType = b.GetType();
MethodInfo incluedMethod = builderType.GetMethod("Include", BindingFlags.Instance | BindingFlags.Public);
MethodInfo excludeMethod = builderType.GetMethod("Exclude", BindingFlags.Instance | BindingFlags.Public);
MethodInfo optionalMethod = builderType.GetMethod("Optional", BindingFlags.Instance | BindingFlags.Public);
Type thisType = q.GetType();
FieldInfo[] fieldInfos = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fieldInfos)
{
Type fieldType = fieldInfo.FieldType;
if (fieldType.IsSubclassOf(typeof(EcsPoolBase)) == false)
continue;
if (fieldType.IsGenericType == false)
continue;
Type componentType = fieldType.GenericTypeArguments[0];
if (fieldInfo.GetCustomAttribute<IncAttribute>() != null)
{
fieldInfo.SetValue(q, incluedMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
if (fieldInfo.GetCustomAttribute<ExcAttribute>() != null)
{
fieldInfo.SetValue(q, excludeMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
if (fieldInfo.GetCustomAttribute<OptAttribute>() != null)
{
fieldInfo.SetValue(q, optionalMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
}
}
}
}

View File

@ -0,0 +1,95 @@
using System;
using System.Reflection;
namespace DCFApixels.DragonECS
{
public abstract class EcsSubjectDI : EcsSubject
{
protected sealed override void Init(Builder b) => EcsQueryDIHelper.Fill(this, b);
}
internal static class EcsQueryDIHelper
{
public static void Fill(EcsSubject s, EcsSubject.Builder b)
{
Type builderType = b.GetType();
MethodInfo incluedMethod = builderType.GetMethod("Include", BindingFlags.Instance | BindingFlags.Public);
MethodInfo excludeMethod = builderType.GetMethod("Exclude", BindingFlags.Instance | BindingFlags.Public);
MethodInfo includeImplicitMethod = builderType.GetMethod("IncludeImplicit", BindingFlags.Instance | BindingFlags.Public);
MethodInfo excludeImplicitMethod = builderType.GetMethod("ExcludeImplicit", BindingFlags.Instance | BindingFlags.Public);
MethodInfo optionalMethod = builderType.GetMethod("Optional", BindingFlags.Instance | BindingFlags.Public);
Type subjectType = s.GetType();
foreach (var attribute in subjectType.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
{
if (attribute is IncImplicitAttribute incImplicit)
{
if (incImplicit.isPool)
incluedMethod.MakeGenericMethod(incImplicit.type.GenericTypeArguments[0], incImplicit.type).Invoke(b, null);
else
includeImplicitMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
continue;
}
if (attribute is ExcImplicitAttribute excImplicit)
{
if (excImplicit.isPool)
excludeMethod.MakeGenericMethod(excImplicit.type.GenericTypeArguments[0], excImplicit.type).Invoke(b, null);
else
excludeImplicitMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
continue;
}
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
FieldInfo[] fieldInfos = subjectType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fieldInfos)
{
Type fieldType = fieldInfo.FieldType;
foreach (var attribute in fieldInfo.GetCustomAttributes<ImplicitInjectAttribute>())//TODO убрать дублирование кода - вынести в отедльный метод
{
if(attribute is IncImplicitAttribute incImplicit)
{
if(incImplicit.isPool)
incluedMethod.MakeGenericMethod(incImplicit.type.GenericTypeArguments[0], incImplicit.type).Invoke(b, null);
else
includeImplicitMethod.MakeGenericMethod(incImplicit.type).Invoke(b, null);
continue;
}
if (attribute is ExcImplicitAttribute excImplicit)
{
if (excImplicit.isPool)
excludeMethod.MakeGenericMethod(excImplicit.type.GenericTypeArguments[0], excImplicit.type).Invoke(b, null);
else
excludeImplicitMethod.MakeGenericMethod(excImplicit.type).Invoke(b, null);
continue;
}
}//TODO КОНЕЦ убрать дублирование кода - вынести в отедльный метод
if (fieldInfo.GetCustomAttribute<InjectAttribute>() == null)
continue;
if (fieldType.IsGenericType == false)
continue;
Type componentType = fieldType.GenericTypeArguments[0];
if (fieldInfo.GetCustomAttribute<IncAttribute>() != null)
{
fieldInfo.SetValue(s, incluedMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
if (fieldInfo.GetCustomAttribute<ExcAttribute>() != null)
{
fieldInfo.SetValue(s, excludeMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
if (fieldInfo.GetCustomAttribute<OptAttribute>() != null)
{
fieldInfo.SetValue(s, optionalMethod.MakeGenericMethod(componentType, fieldType).Invoke(b, null));
continue;
}
}
}
}
}