diff --git a/Convention-CSharp.csproj b/Convention-CSharp.csproj index cdc5c57..1bb1198 100644 --- a/Convention-CSharp.csproj +++ b/Convention-CSharp.csproj @@ -5,8 +5,6 @@ Exe net8.0 Convention - enable - enable diff --git a/Convention/Runtime/Architecture.cs b/Convention/Runtime/Architecture.cs index 5daa48f..18369af 100644 --- a/Convention/Runtime/Architecture.cs +++ b/Convention/Runtime/Architecture.cs @@ -3,33 +3,40 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using static System.Runtime.InteropServices.JavaScript.JSType; +using Microsoft.VisualBasic; namespace Convention { // Interface + public interface ISignal + { + + } + public interface IModel { string Save(); void Load(string data); } - public interface IConvertModel - : IModel + public interface IConvertable { T ConvertTo(); } + public interface IConvertModel + : IModel, IConvertable + { + } + // Instance public class SingletonModel: IModel { - private static T? InjectInstance = default; + private static T InjectInstance = default; - public static T? Instance + public static T Instance { get => InjectInstance; set @@ -43,7 +50,7 @@ namespace Convention } } - public T? Data => InjectInstance; + public T Data => InjectInstance; void IModel.Load(string data) { @@ -63,7 +70,7 @@ namespace Convention throw new InvalidOperationException(); } - public static implicit operator T?(SingletonModel _) => InjectInstance; + public static implicit operator T(SingletonModel _) => InjectInstance; } public class DependenceModel @@ -118,10 +125,10 @@ namespace Convention return type.Assembly + "::" + type.FullName; } - public static Type? LoadFromFormat(string data) + public static Type LoadFromFormat(string data) { var keys = data.Split("::"); - Assembly? asm = null; + Assembly asm = null; try { asm = Assembly.LoadFrom(keys[0]); @@ -133,11 +140,11 @@ namespace Convention } } - public static Type? LoadFromFormat(string data, out Exception? exception) + public static Type LoadFromFormat(string data, out Exception exception) { exception = null; var keys = data.Split("::"); - Assembly? asm = null; + Assembly asm = null; try { asm = Assembly.LoadFrom(keys[0]); @@ -150,6 +157,23 @@ namespace Convention } } + internal static void InternalReset() + { + // Register System + RegisterHistory.Clear(); + UncompleteTargets.Clear(); + Completer.Clear(); + Dependences.Clear(); + Childs.Clear(); + // Event Listener + SignalListener.Clear(); + // Linear Chain for Dependence + TimelineQuenes.Clear(); + TimelineContentID = 0; + } + + #region Objects Registered + private class TypeQuery : IConvertModel { @@ -176,11 +200,11 @@ namespace Convention } } - private static HashSet RegisterHistory = new(); - private static Dictionary UncompleteTargets = new(); - private static Dictionary Completer = new(); - private static Dictionary Dependences = new(); - private static Dictionary Childs = new(); + private static readonly HashSet RegisterHistory = new(); + private static readonly Dictionary UncompleteTargets = new(); + private static readonly Dictionary Completer = new(); + private static readonly Dictionary Dependences = new(); + private static readonly Dictionary Childs = new(); public class Registering : IConvertModel { @@ -207,7 +231,7 @@ namespace Convention } } - private static bool InternalComplete(out HashSet InternalUpdateBuffer) + private static bool InternalRegisteringComplete(out HashSet InternalUpdateBuffer) { InternalUpdateBuffer = new(); bool result = false; @@ -222,19 +246,22 @@ namespace Convention return result; } - private static void InternalUpdate(HashSet InternalUpdateBuffer) + private static void InternalRegisteringUpdate(HashSet InternalUpdateBuffer) { foreach (var complete in InternalUpdateBuffer) { Dependences.Remove(complete); - + } + foreach (var complete in InternalUpdateBuffer) + { + Completer[complete](); + Completer.Remove(complete); } foreach (var complete in InternalUpdateBuffer) { Childs.Add(complete, UncompleteTargets[complete]); UncompleteTargets.Remove(complete); } - InternalUpdateBuffer.Clear(); } public static Registering Register(Type slot, object target, Action completer, params Type[] dependences) @@ -245,9 +272,9 @@ namespace Convention } Completer[slot] = completer; UncompleteTargets[slot] = target; - Dependences[slot] = new DependenceModel(from dependence in dependences select new TypeQuery(dependence)); - while (InternalComplete(out var buffer)) - InternalUpdate(buffer); + Dependences[slot] = new DependenceModel(from dependence in dependences where dependence != slot select new TypeQuery(dependence)); + while (InternalRegisteringComplete(out var buffer)) + InternalRegisteringUpdate(buffer); return new Registering(slot); } @@ -262,5 +289,124 @@ namespace Convention public static object Get(Type type) => InternalGet(type); public static T Get() => (T)Get(typeof(T)); + + #endregion + + #region Signal & Update + + private static readonly Dictionary>> SignalListener = new(); + + public class Listening + { + private readonly Action action; + private readonly Type type; + + public Listening(Action action, Type type) + { + this.action = action; + this.type = type; + } + + public void StopListening() + { + if (SignalListener.TryGetValue(type, out var actions)) + actions.Remove(action); + } + } + + public static Listening AddListener(Type slot, Action listener) where Signal : ISignal + { + if (SignalListener.ContainsKey(slot) == false) + SignalListener.Add(slot, new()); + Action action = x => + { + if (x is Signal signal) + listener(signal); + }; + Listening result = new(action, slot); + SignalListener[slot].Add(action); + return result; + } + + public static void SendMessage(Type slot, ISignal signal) + { + if(SignalListener.TryGetValue(slot,out var actions)) + { + foreach (var action in actions) + { + action(signal); + } + } + } + + public static void SendMessage(Signal signal) where Signal : ISignal => SendMessage(signal.GetType(), signal); + + #endregion + + #region Timeline/Chain & Update + + private class TimelineQueneEntry + { + public Func predicate; + public List actions = new(); + } + + private class Timeline + { + public Dictionary, int> PredicateMapper = new(); + public List Quene = new(); + public int Context = 0; + } + + private static Dictionary TimelineQuenes = new(); + private static int TimelineContentID = 0; + + public static int CreateTimeline() + { + TimelineQuenes.Add(TimelineContentID++, new()); + return TimelineQuenes.Count; + } + + public static void AddStep(int timelineId, Func predicate,params Action[] actions) + { + var timeline = TimelineQuenes[timelineId]; + if (timeline.PredicateMapper.TryGetValue(predicate, out var time)) + { + timeline.Quene[time].actions.AddRange(actions); + } + else + { + time = timeline.Quene.Count; + timeline.PredicateMapper.Add(predicate, time); + timeline.Quene.Add(new() + { + predicate = predicate, + actions = actions.ToList() + }); + } + } + + public static void UpdateTimeline() + { + foreach (var pair in TimelineQuenes) + { + var timeline = pair.Value; + if(timeline.Quene[timeline.Context].predicate()) + { + foreach (var action in timeline.Quene[timeline.Context].actions) + { + action(); + } + timeline.Context++; + } + } + } + + public static void ResetTimelineContext(int timelineId) + { + TimelineQuenes[timelineId].Context = 0; + } + + #endregion } } diff --git a/Convention/Runtime/Config.cs b/Convention/Runtime/Config.cs index abd0192..a0cd628 100644 --- a/Convention/Runtime/Config.cs +++ b/Convention/Runtime/Config.cs @@ -6,5 +6,59 @@ using System.Threading.Tasks; namespace Convention { + namespace NTree + { + public class NTreeNode + { + public NTreeNode Parent; + public NTreeNode Child; + public NTreeNode Right; + public T Data; + public int BranchSize() + { + if (Parent == null) + return -1; + var left = Parent.Child; + int result = 0; + while (left != null) + result++; + return result; + } + + public int BranchLeftCount() + { + if (Parent == null) + return -1; + var left = Parent.Child; + int result = 0; + while (left != this) + result++; + return result; + } + + public int BranchRightSize() + { + var left = this; + int result = 0; + while (left != null) + result++; + return result; + } + } + + public class NTree + { + internal NTreeNode Root; + + public bool IsEmpty() => Root == null; + + public NTreeNode UpdateRoot(NTreeNode node) + { + var oldRoot = Root; + Root = node; + return oldRoot; + } + } + } } diff --git a/[Test]/Program.cs b/[Test]/Program.cs index 3849a54..cd10e48 100644 --- a/[Test]/Program.cs +++ b/[Test]/Program.cs @@ -1,9 +1,48 @@ -using Convention; +using System; +using System.Collections.Generic; +using System.Threading; +using Convention; public class Program { + class Slot1 + { + + } + class Slot2 + { + + } + class Slot3 + { + + } + class Slot4 + { + + } + static void Main(string[] args) { - Console.WriteLine("Hello, World!"); + var seed = new Random(2049); + for (int i = 0; i < 100000; i++) + { + Convention.Architecture.InternalReset(); + var slot1 = new Slot1(); + var slot2 = new Slot2(); + var slot3 = new Slot3(); + var slot4 = new Slot4(); + List list = new() { + ()=> Convention.Architecture.Register(slot1,()=>{ },typeof(Slot2),typeof(Slot3),typeof(Slot4)), + ()=> Convention.Architecture.Register(slot2,()=>{ },typeof(Slot3),typeof(Slot4)), + ()=> Convention.Architecture.Register(slot3,()=>{ },typeof(Slot4)), + ()=> Convention.Architecture.Register(slot4,()=>{ })}; + list.Sort((x, y) => seed.Next() > seed.Next() ? 1 : -1); + foreach (var item in list) + { + item(); + } + Console.Write($"{i}\t\r"); + } } } \ No newline at end of file