DragonECS/src/Builtin/InjectSystem.cs

242 lines
9.5 KiB
C#
Raw Normal View History

2023-03-29 15:48:37 +08:00
using DCFApixels.DragonECS.Internal;
2023-04-23 17:55:01 +08:00
using DCFApixels.DragonECS.RunnersCore;
2023-05-30 01:31:04 +08:00
using System;
2023-03-29 06:19:24 +08:00
namespace DCFApixels.DragonECS
{
2024-01-26 02:26:17 +08:00
public readonly struct Injector
{
private readonly EcsPipeline _pipeline;
public Injector(EcsPipeline pipeline)
{
_pipeline = pipeline;
}
public void Inject<T>(T data)
{
_pipeline.Inject(data);
}
}
public interface IInjectionBlock
{
void InjectTo(Injector i);
}
[MetaName(nameof(PreInject))]
2023-12-06 20:38:00 +08:00
[BindWithEcsRunner(typeof(EcsPreInjectRunner))]
2023-05-30 18:27:30 +08:00
public interface IEcsPreInject : IEcsProcess
2023-05-26 03:45:35 +08:00
{
void PreInject(object obj);
}
[MetaName(nameof(Inject))]
2023-12-06 20:38:00 +08:00
[BindWithEcsRunner(typeof(EcsInjectRunner<>))]
2023-05-30 18:27:30 +08:00
public interface IEcsInject<T> : IEcsProcess
2023-05-26 03:45:35 +08:00
{
void Inject(T obj);
}
[MetaName("PreInitInject")]
[BindWithEcsRunner(typeof(EcsPreInitInjectProcessRunner))]
2023-05-30 18:27:30 +08:00
public interface IEcsPreInitInjectProcess : IEcsProcess
2023-05-26 03:45:35 +08:00
{
void OnPreInitInjectionBefore();
void OnPreInitInjectionAfter();
}
2023-03-29 06:19:24 +08:00
namespace Internal
{
2024-02-17 00:10:38 +08:00
internal class InitInjectController
2023-03-29 06:19:24 +08:00
{
2023-03-30 05:32:43 +08:00
private EcsPipeline _source;
2024-02-17 00:10:38 +08:00
private InitInjectSystemBase[] _injectSystems;
2023-03-29 06:19:24 +08:00
private int _injectCount;
2024-02-17 00:10:38 +08:00
public bool IsInjectionEnd
{
get { return _injectCount >= _injectSystems.Length; }
}
public InitInjectController(EcsPipeline source)
2023-03-29 06:19:24 +08:00
{
_injectCount = 0;
_source = source;
2024-02-17 00:10:38 +08:00
_injectSystems = _source.GetSystems<InitInjectSystemBase>();
2023-03-29 06:19:24 +08:00
}
public bool OnInject()
{
_injectCount++;
return IsInjectionEnd;
}
public void Destroy()
{
_source = null;
_injectSystems = null;
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsPreInjectRunner : EcsRunner<IEcsPreInject>, IEcsPreInject
2023-03-29 06:19:24 +08:00
{
2023-04-23 18:05:27 +08:00
void IEcsPreInject.PreInject(object obj)
{
2024-01-26 02:26:17 +08:00
if (obj is IInjectionBlock container)
{
container.InjectTo(new Injector(Pipeline));
}
foreach (var item in targets)
{
item.PreInject(obj);
}
2023-04-23 18:05:27 +08:00
}
2023-03-29 06:19:24 +08:00
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsInjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
2023-03-29 06:19:24 +08:00
{
2023-05-30 01:31:04 +08:00
private EcsBaseTypeInjectRunner _baseTypeInjectRunner;
2023-04-23 18:05:27 +08:00
void IEcsInject<T>.Inject(T obj)
{
2023-06-26 01:57:50 +08:00
if (obj == null) Throw.ArgumentNull();
2023-05-30 01:31:04 +08:00
_baseTypeInjectRunner.Inject(obj);
2023-04-23 18:05:27 +08:00
foreach (var item in targets) item.Inject(obj);
}
protected override void OnSetup()
{
2023-05-30 01:31:04 +08:00
Type baseType = typeof(T).BaseType;
if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType != null)
2024-01-26 02:26:17 +08:00
_baseTypeInjectRunner = (EcsBaseTypeInjectRunner)Activator.CreateInstance(typeof(EcsBaseTypeInjectRunner<>).MakeGenericType(baseType), Pipeline);
2023-05-30 01:31:04 +08:00
else
2024-01-26 02:26:17 +08:00
_baseTypeInjectRunner = new EcsObjectTypePreInjectRunner(Pipeline);
2023-04-23 18:05:27 +08:00
}
}
2023-05-30 01:31:04 +08:00
internal abstract class EcsBaseTypeInjectRunner
{
public abstract void Inject(object obj);
}
2023-12-31 17:58:20 +08:00
internal sealed class EcsBaseTypeInjectRunner<T> : EcsBaseTypeInjectRunner
2023-05-30 01:31:04 +08:00
{
private IEcsInject<T> _runner;
public EcsBaseTypeInjectRunner(EcsPipeline pipeline) => _runner = pipeline.GetRunner<IEcsInject<T>>();
2023-12-31 17:58:20 +08:00
public sealed override void Inject(object obj) => _runner.Inject((T)obj);
2023-05-30 01:31:04 +08:00
}
2023-12-31 17:58:20 +08:00
internal sealed class EcsObjectTypePreInjectRunner : EcsBaseTypeInjectRunner
2023-05-30 01:31:04 +08:00
{
private IEcsPreInject _runner;
public EcsObjectTypePreInjectRunner(EcsPipeline pipeline) => _runner = pipeline.GetRunner<IEcsPreInject>();
2023-12-31 17:58:20 +08:00
public sealed override void Inject(object obj) => _runner.PreInject(obj);
2023-05-30 01:31:04 +08:00
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsPreInitInjectProcessRunner : EcsRunner<IEcsPreInitInjectProcess>, IEcsPreInitInjectProcess
2023-04-23 18:05:27 +08:00
{
public void OnPreInitInjectionAfter()
{
foreach (var item in targets) item.OnPreInitInjectionAfter();
}
public void OnPreInitInjectionBefore()
{
foreach (var item in targets) item.OnPreInitInjectionBefore();
}
2023-03-12 02:02:39 +08:00
}
2024-02-17 00:10:38 +08:00
public abstract class InitInjectSystemBase { }
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
2024-02-17 00:10:38 +08:00
public class InitInjectSystem<T> : InitInjectSystemBase, IEcsPipelineMember, IEcsInject<InitInjectController>, IEcsPreInitInjectProcess
{
private EcsPipeline _pipeline;
2024-02-17 00:10:38 +08:00
public EcsPipeline Pipeline
{
get { return Pipeline; }
set
{
_pipeline = value;
2024-02-17 00:10:38 +08:00
if (_injectedData == null)
{
return;
}
if (_injectController == null)
{
var injectPipelineRunner = _pipeline.GetRunner<IEcsInject<EcsPipeline>>();
injectPipelineRunner.Inject(_pipeline);
EcsRunner.Destroy(injectPipelineRunner);
_injectController = new InitInjectController(_pipeline);
var injectMapRunner = _pipeline.GetRunner<IEcsInject<InitInjectController>>();
_pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
injectMapRunner.Inject(_injectController);
EcsRunner.Destroy(injectMapRunner);
}
var injectRunnerGeneric = _pipeline.GetRunner<IEcsInject<T>>();
injectRunnerGeneric.Inject(_injectedData);
if (_injectController.OnInject())
{
_injectController.Destroy();
var injectCallbacksRunner = _pipeline.GetRunner<IEcsPreInitInjectProcess>();
injectCallbacksRunner.OnPreInitInjectionAfter();
EcsRunner.Destroy(injectCallbacksRunner);
}
_injectedData = default;
}
}
2024-02-17 00:10:38 +08:00
private InitInjectController _injectController;
void IEcsInject<InitInjectController>.Inject(InitInjectController obj) { _injectController = obj; }
private T _injectedData;
internal InitInjectSystem(T injectedData)
2023-03-29 15:48:37 +08:00
{
2023-06-26 01:57:50 +08:00
if (injectedData == null) Throw.ArgumentNull();
2023-05-26 03:45:35 +08:00
_injectedData = injectedData;
2023-03-29 06:19:24 +08:00
}
2024-02-17 00:10:38 +08:00
void IEcsPreInitInjectProcess.OnPreInitInjectionBefore() { }
void IEcsPreInitInjectProcess.OnPreInitInjectionAfter() { _injectController = null; }
}
}
2023-06-22 14:31:13 +08:00
public static partial class EcsPipelineExtensions
{
2024-01-26 02:26:17 +08:00
public static void Inject<T>(this EcsPipeline self, T data)
{
self.GetRunner<IEcsInject<T>>().Inject(data);
}
2023-06-22 14:31:13 +08:00
}
public static partial class EcsPipelineBuilderExtensions
{
2023-03-30 05:32:43 +08:00
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
{
2023-06-26 01:57:50 +08:00
if (data == null) Throw.ArgumentNull();
2024-02-17 00:10:38 +08:00
self.Add(new InitInjectSystem<T>(data));
if (data is IEcsModule module)
self.AddModule(module);
return self;
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1>(this EcsPipeline.Builder self, T0 d0, T1 d1)
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1);
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2)
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2);
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2, T3>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3)
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3);
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4)
2023-03-26 11:19:03 +08:00
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4);
2023-03-26 11:19:03 +08:00
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f)
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f);
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5, T6>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6)
2023-04-24 17:34:38 +08:00
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6);
2023-04-24 17:34:38 +08:00
}
2024-01-26 02:26:17 +08:00
public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5, T6, T7>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6, T7 d7)
2023-04-24 17:34:38 +08:00
{
2024-01-26 02:26:17 +08:00
return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6).Inject(d7);
2023-04-24 17:34:38 +08:00
}
}
}