add explicit binding of process to runner

This commit is contained in:
Mikhail 2023-12-06 20:34:33 +08:00
parent 6e16e2962e
commit 91a750394e
3 changed files with 52 additions and 2 deletions

View File

@ -1,22 +1,27 @@
#pragma warning disable CS0162 // Обнаружен недостижимый код #pragma warning disable CS0162 // Обнаружен недостижимый код
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.RunnersCore; using DCFApixels.DragonECS.RunnersCore;
using System; using System;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
#region Interfaces #region Interfaces
[EcsBindWithRunner(typeof(EcsPreInitProcessRunner))]
public interface IEcsPreInitProcess : IEcsProcess public interface IEcsPreInitProcess : IEcsProcess
{ {
void PreInit(); void PreInit();
} }
[EcsBindWithRunner(typeof(EcsInitProcessRunner))]
public interface IEcsInitProcess : IEcsProcess public interface IEcsInitProcess : IEcsProcess
{ {
void Init(); void Init();
} }
[EcsBindWithRunner(typeof(EcsRunProcessRunner))]
public interface IEcsRunProcess : IEcsProcess public interface IEcsRunProcess : IEcsProcess
{ {
void Run(); void Run();
} }
[EcsBindWithRunner(typeof(EcsDestroyProcessRunner))]
public interface IEcsDestroyProcess : IEcsProcess public interface IEcsDestroyProcess : IEcsProcess
{ {
void Destroy(); void Destroy();

View File

@ -5,10 +5,12 @@ using System.Linq;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[EcsBindWithRunner(typeof(EcsPreInjectRunner))]
public interface IEcsPreInject : IEcsProcess public interface IEcsPreInject : IEcsProcess
{ {
void PreInject(object obj); void PreInject(object obj);
} }
[EcsBindWithRunner(typeof(EcsInjectRunner<>))]
public interface IEcsInject<T> : IEcsProcess public interface IEcsInject<T> : IEcsProcess
{ {
void Inject(T obj); void Inject(T obj);

View File

@ -23,6 +23,31 @@ namespace DCFApixels.DragonECS
} }
public EcsRunnerFilterAttribute(object filter) : this(null, filter) { } public EcsRunnerFilterAttribute(object filter) : this(null, filter) { }
} }
#if UNITY_2020_3_OR_NEWER
[UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
#endif
[AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
public sealed class EcsBindWithRunnerAttribute : Attribute
{
private static readonly Type baseType = typeof(EcsRunner<>);
public readonly Type runnerType;
public EcsBindWithRunnerAttribute(Type runnerType)
{
if (runnerType == null)
throw new ArgumentNullException();
if (!Check(runnerType))
throw new ArgumentException();
this.runnerType = runnerType;
}
private bool Check(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == baseType)
return true;
if (type.BaseType != null)
return Check(type.BaseType);
return false;
}
}
public interface IEcsProcess { } public interface IEcsProcess { }
@ -188,7 +213,25 @@ namespace DCFApixels.DragonECS
#region Instantiate #region Instantiate
private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter) private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter)
{ {
if (_subclass == null) EcsRunnerActivator.InitFor<TInterface>(); if(_subclass == null)
{
Type interfaceType = typeof(TInterface);
if (interfaceType.TryGetAttribute(out EcsBindWithRunnerAttribute atr))
{
Type runnerType = atr.runnerType;
if (interfaceType.IsGenericType)
{
Type[] genericTypes = interfaceType.GetGenericArguments();
runnerType = runnerType.MakeGenericType(genericTypes);
}
_subclass = runnerType;
}
else
{
EcsRunnerActivator.InitFor<TInterface>();
}
}
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass); var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
return (TInterface)(IEcsProcess)instance.Set(source, targets, isHasFilter, filter); return (TInterface)(IEcsProcess)instance.Set(source, targets, isHasFilter, filter);
} }
@ -201,7 +244,7 @@ namespace DCFApixels.DragonECS
return Instantiate(source, FilterSystems(source.AllSystems, filter), true, filter); return Instantiate(source, FilterSystems(source.AllSystems, filter), true, filter);
} }
#endregion #endregion
private EcsPipeline _source; private EcsPipeline _source;
protected TInterface[] targets; protected TInterface[] targets;
private ReadOnlyCollection<TInterface> _targetsSealed; private ReadOnlyCollection<TInterface> _targetsSealed;