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 // Обнаружен недостижимый код
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.RunnersCore;
using System;
namespace DCFApixels.DragonECS
{
#region Interfaces
[EcsBindWithRunner(typeof(EcsPreInitProcessRunner))]
public interface IEcsPreInitProcess : IEcsProcess
{
void PreInit();
}
[EcsBindWithRunner(typeof(EcsInitProcessRunner))]
public interface IEcsInitProcess : IEcsProcess
{
void Init();
}
[EcsBindWithRunner(typeof(EcsRunProcessRunner))]
public interface IEcsRunProcess : IEcsProcess
{
void Run();
}
[EcsBindWithRunner(typeof(EcsDestroyProcessRunner))]
public interface IEcsDestroyProcess : IEcsProcess
{
void Destroy();

View File

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

View File

@ -23,6 +23,31 @@ namespace DCFApixels.DragonECS
}
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 { }
@ -188,7 +213,25 @@ namespace DCFApixels.DragonECS
#region Instantiate
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);
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);
}
#endregion
private EcsPipeline _source;
protected TInterface[] targets;
private ReadOnlyCollection<TInterface> _targetsSealed;