/**************************************************************************** * Copyright (c) 2015 ~ 2022 liangxiegame MIT License * * QFramework v1.0 * * https://qframework.cn * https://github.com/liangxiegame/QFramework * https://gitee.com/liangxiegame/QFramework * * Author: * liangxie https://github.com/liangxie * soso https://github.com/so-sos-so * * Contributor * TastSong https://github.com/TastSong * 京产肠饭 https://gitee.com/JingChanChangFan/hk_-unity-tools * 猫叔(一只皮皮虾) https://space.bilibili.com/656352/ * * Community * QQ Group: 623597263 * Latest Update: 2022.8.8 10:24 List=>HashSet ****************************************************************************/ using System; using System.Collections.Generic; using UnityEngine; namespace QFramework { #region Architecture public interface IArchitecture { void RegisterSystem(T system) where T : ISystem; void RegisterModel(T model) where T : IModel; void RegisterUtility(T utility) where T : IUtility; T GetSystem() where T : class, ISystem; T GetModel() where T : class, IModel; T GetUtility() where T : class, IUtility; void SendCommand() where T : ICommand, new(); void SendCommand(T command) where T : ICommand; TResult SendQuery(IQuery query); void SendEvent() where T : new(); void SendEvent(T e); IUnRegister RegisterEvent(Action onEvent); void UnRegisterEvent(Action onEvent); } public abstract class Architecture : IArchitecture where T : Architecture, new() { private bool mInited = false; private HashSet mSystems = new HashSet(); private HashSet mModels = new HashSet(); public static Action OnRegisterPatch = architecture => { }; private static T mArchitecture; public static IArchitecture Interface { get { if (mArchitecture == null) { MakeSureArchitecture(); } return mArchitecture; } } static void MakeSureArchitecture() { if (mArchitecture == null) { mArchitecture = new T(); mArchitecture.Init(); OnRegisterPatch?.Invoke(mArchitecture); foreach (var architectureModel in mArchitecture.mModels) { architectureModel.Init(); } mArchitecture.mModels.Clear(); foreach (var architectureSystem in mArchitecture.mSystems) { architectureSystem.Init(); } mArchitecture.mSystems.Clear(); mArchitecture.mInited = true; } } protected abstract void Init(); private IOCContainer mContainer = new IOCContainer(); public void RegisterSystem(TSystem system) where TSystem : ISystem { system.SetArchitecture(this); mContainer.Register(system); if (!mInited) { mSystems.Add(system); } else { system.Init(); } } public void RegisterModel(TModel model) where TModel : IModel { model.SetArchitecture(this); mContainer.Register(model); if (!mInited) { mModels.Add(model); } else { model.Init(); } } public void RegisterUtility(TUtility utility) where TUtility : IUtility { mContainer.Register(utility); } public TSystem GetSystem() where TSystem : class, ISystem { return mContainer.Get(); } public TModel GetModel() where TModel : class, IModel { return mContainer.Get(); } public TUtility GetUtility() where TUtility : class, IUtility { return mContainer.Get(); } public void SendCommand() where TCommand : ICommand, new() { var command = new TCommand(); ExecuteCommand(command); } public void SendCommand(TCommand command) where TCommand : ICommand { ExecuteCommand(command); } protected virtual void ExecuteCommand(ICommand command) { command.SetArchitecture(this); command.Execute(); } public TResult SendQuery(IQuery query) { return DoQuery(query); } protected virtual TResult DoQuery(IQuery query) { query.SetArchitecture(this); return query.Do(); } private TypeEventSystem mTypeEventSystem = new TypeEventSystem(); public void SendEvent() where TEvent : new() { mTypeEventSystem.Send(); } public void SendEvent(TEvent e) { mTypeEventSystem.Send(e); } public IUnRegister RegisterEvent(Action onEvent) { return mTypeEventSystem.Register(onEvent); } public void UnRegisterEvent(Action onEvent) { mTypeEventSystem.UnRegister(onEvent); } } public interface IOnEvent { void OnEvent(T e); } public static class OnGlobalEventExtension { public static IUnRegister RegisterEvent(this IOnEvent self) where T : struct { return TypeEventSystem.Global.Register(self.OnEvent); } public static void UnRegisterEvent(this IOnEvent self) where T : struct { TypeEventSystem.Global.UnRegister(self.OnEvent); } } #endregion #region Controller public interface IController : IBelongToArchitecture, ICanSendCommand, ICanGetSystem, ICanGetModel, ICanRegisterEvent, ICanSendQuery { } #endregion #region System public interface ISystem : IBelongToArchitecture, ICanSetArchitecture, ICanGetModel, ICanGetUtility, ICanRegisterEvent, ICanSendEvent, ICanGetSystem { void Init(); } public abstract class AbstractSystem : ISystem { private IArchitecture mArchitecture; IArchitecture IBelongToArchitecture.GetArchitecture() { return mArchitecture; } void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) { mArchitecture = architecture; } void ISystem.Init() { OnInit(); } protected abstract void OnInit(); } #endregion #region Model public interface IModel : IBelongToArchitecture, ICanSetArchitecture, ICanGetUtility, ICanSendEvent { void Init(); } public abstract class AbstractModel : IModel { private IArchitecture mArchitecturel; IArchitecture IBelongToArchitecture.GetArchitecture() { return mArchitecturel; } void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) { mArchitecturel = architecture; } void IModel.Init() { OnInit(); } protected abstract void OnInit(); } #endregion #region Utility public interface IUtility { } #endregion #region Command public interface ICommand : IBelongToArchitecture, ICanSetArchitecture, ICanGetSystem, ICanGetModel, ICanGetUtility, ICanSendEvent, ICanSendCommand, ICanSendQuery { void Execute(); } public abstract class AbstractCommand : ICommand { private IArchitecture mArchitecture; IArchitecture IBelongToArchitecture.GetArchitecture() { return mArchitecture; } void ICanSetArchitecture.SetArchitecture(IArchitecture architecture) { mArchitecture = architecture; } void ICommand.Execute() { OnExecute(); } protected abstract void OnExecute(); } #endregion #region Query public interface IQuery : IBelongToArchitecture, ICanSetArchitecture, ICanGetModel, ICanGetSystem, ICanSendQuery { TResult Do(); } public abstract class AbstractQuery : IQuery { public T Do() { return OnDo(); } protected abstract T OnDo(); private IArchitecture mArchitecture; public IArchitecture GetArchitecture() { return mArchitecture; } public void SetArchitecture(IArchitecture architecture) { mArchitecture = architecture; } } #endregion #region Rule public interface IBelongToArchitecture { IArchitecture GetArchitecture(); } public interface ICanSetArchitecture { void SetArchitecture(IArchitecture architecture); } public interface ICanGetModel : IBelongToArchitecture { } public static class CanGetModelExtension { public static T GetModel(this ICanGetModel self) where T : class, IModel { return self.GetArchitecture().GetModel(); } } public interface ICanGetSystem : IBelongToArchitecture { } public static class CanGetSystemExtension { public static T GetSystem(this ICanGetSystem self) where T : class, ISystem { return self.GetArchitecture().GetSystem(); } } public interface ICanGetUtility : IBelongToArchitecture { } public static class CanGetUtilityExtension { public static T GetUtility(this ICanGetUtility self) where T : class, IUtility { return self.GetArchitecture().GetUtility(); } } public interface ICanRegisterEvent : IBelongToArchitecture { } public static class CanRegisterEventExtension { public static IUnRegister RegisterEvent(this ICanRegisterEvent self, Action onEvent) { return self.GetArchitecture().RegisterEvent(onEvent); } public static void UnRegisterEvent(this ICanRegisterEvent self, Action onEvent) { self.GetArchitecture().UnRegisterEvent(onEvent); } } public interface ICanSendCommand : IBelongToArchitecture { } public static class CanSendCommandExtension { public static void SendCommand(this ICanSendCommand self) where T : ICommand, new() { self.GetArchitecture().SendCommand(); } public static void SendCommand(this ICanSendCommand self, T command) where T : ICommand { self.GetArchitecture().SendCommand(command); } } public interface ICanSendEvent : IBelongToArchitecture { } public static class CanSendEventExtension { public static void SendEvent(this ICanSendEvent self) where T : new() { self.GetArchitecture().SendEvent(); } public static void SendEvent(this ICanSendEvent self, T e) { self.GetArchitecture().SendEvent(e); } } public interface ICanSendQuery : IBelongToArchitecture { } public static class CanSendQueryExtension { public static TResult SendQuery(this ICanSendQuery self, IQuery query) { return self.GetArchitecture().SendQuery(query); } } #endregion #region TypeEventSystem public interface IUnRegister { void UnRegister(); } public interface IUnRegisterList { List UnregisterList { get; } } public static class IUnRegisterListExtension { public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList) { unRegisterList.UnregisterList.Add(self); } public static void UnRegisterAll(this IUnRegisterList self) { foreach (var unRegister in self.UnregisterList) { unRegister.UnRegister(); } self.UnregisterList.Clear(); } } /// /// 自定义可注销的类 /// public struct CustomUnRegister : IUnRegister { /// /// 委托对象 /// private Action mOnUnRegister { get; set; } /// /// 带参构造函数 /// /// public CustomUnRegister(Action onUnRegsiter) { mOnUnRegister = onUnRegsiter; } /// /// 资源释放 /// public void UnRegister() { mOnUnRegister.Invoke(); mOnUnRegister = null; } } public class UnRegisterOnDestroyTrigger : MonoBehaviour { private readonly HashSet mUnRegisters = new HashSet(); public void AddUnRegister(IUnRegister unRegister) { mUnRegisters.Add(unRegister); } public void RemoveUnRegister(IUnRegister unRegister) { mUnRegisters.Remove(unRegister); } private void OnDestroy() { foreach (var unRegister in mUnRegisters) { unRegister.UnRegister(); } mUnRegisters.Clear(); } } public static class UnRegisterExtension { public static IUnRegister UnRegisterWhenGameObjectDestroyed(this IUnRegister unRegister, GameObject gameObject) { var trigger = gameObject.GetComponent(); if (!trigger) { trigger = gameObject.AddComponent(); } trigger.AddUnRegister(unRegister); return unRegister; } } public class TypeEventSystem { private readonly EasyEvents mEvents = new EasyEvents(); public static readonly TypeEventSystem Global = new TypeEventSystem(); public void Send() where T : new() { mEvents.GetEvent>()?.Trigger(new T()); } public void Send(T e) { mEvents.GetEvent>()?.Trigger(e); } public IUnRegister Register(Action onEvent) { var e = mEvents.GetOrAddEvent>(); return e.Register(onEvent); } public void UnRegister(Action onEvent) { var e = mEvents.GetEvent>(); if (e != null) { e.UnRegister(onEvent); } } } #endregion #region IOC public class IOCContainer { private Dictionary mInstances = new Dictionary(); public void Register(T instance) { var key = typeof(T); if (mInstances.ContainsKey(key)) { mInstances[key] = instance; } else { mInstances.Add(key, instance); } } public T Get() where T : class { var key = typeof(T); if (mInstances.TryGetValue(key, out var retInstance)) { return retInstance as T; } return null; } } #endregion #region BindableProperty public interface IBindableProperty : IReadonlyBindableProperty { new T Value { get; set; } void SetValueWithoutEvent(T newValue); } public interface IReadonlyBindableProperty { T Value { get; } IUnRegister RegisterWithInitValue(Action action); void UnRegister(Action onValueChanged); IUnRegister Register(Action onValueChanged); } public class BindableProperty : IBindableProperty { public BindableProperty(T defaultValue = default) { mValue = defaultValue; } protected T mValue; public T Value { get => GetValue(); set { if (value == null && mValue == null) return; if (value != null && value.Equals(mValue)) return; SetValue(value); mOnValueChanged?.Invoke(value); } } protected virtual void SetValue(T newValue) { mValue = newValue; } protected virtual T GetValue() { return mValue; } public void SetValueWithoutEvent(T newValue) { mValue = newValue; } private Action mOnValueChanged = (v) => { }; public IUnRegister Register(Action onValueChanged) { mOnValueChanged += onValueChanged; return new BindablePropertyUnRegister() { BindableProperty = this, OnValueChanged = onValueChanged }; } public IUnRegister RegisterWithInitValue(Action onValueChanged) { onValueChanged(mValue); return Register(onValueChanged); } public static implicit operator T(BindableProperty property) { return property.Value; } public override string ToString() { return Value.ToString(); } public void UnRegister(Action onValueChanged) { mOnValueChanged -= onValueChanged; } public string Trim() { throw new NotImplementedException(); } } public class BindablePropertyUnRegister : IUnRegister { public BindableProperty BindableProperty { get; set; } public Action OnValueChanged { get; set; } public void UnRegister() { BindableProperty.UnRegister(OnValueChanged); BindableProperty = null; OnValueChanged = null; } } #endregion #region EasyEvent public interface IEasyEvent { } public class EasyEvent : IEasyEvent { private Action mOnEvent = () => { }; public IUnRegister Register(Action onEvent) { mOnEvent += onEvent; return new CustomUnRegister(() => { UnRegister(onEvent); }); } public void UnRegister(Action onEvent) { mOnEvent -= onEvent; } public void Trigger() { mOnEvent?.Invoke(); } } public class EasyEvent : IEasyEvent { private Action mOnEvent = e => { }; public IUnRegister Register(Action onEvent) { mOnEvent += onEvent; return new CustomUnRegister(() => { UnRegister(onEvent); }); } public void UnRegister(Action onEvent) { mOnEvent -= onEvent; } public void Trigger(T t) { mOnEvent?.Invoke(t); } } public class EasyEvent : IEasyEvent { private Action mOnEvent = (t, k) => { }; public IUnRegister Register(Action onEvent) { mOnEvent += onEvent; return new CustomUnRegister(() => { UnRegister(onEvent); }); } public void UnRegister(Action onEvent) { mOnEvent -= onEvent; } public void Trigger(T t, K k) { mOnEvent?.Invoke(t, k); } } public class EasyEvent : IEasyEvent { private Action mOnEvent = (t, k, s) => { }; public IUnRegister Register(Action onEvent) { mOnEvent += onEvent; return new CustomUnRegister(() => { UnRegister(onEvent); }); } public void UnRegister(Action onEvent) { mOnEvent -= onEvent; } public void Trigger(T t, K k, S s) { mOnEvent?.Invoke(t, k, s); } } public class EasyEvents { private static EasyEvents mGlobalEvents = new EasyEvents(); public static T Get() where T : IEasyEvent { return mGlobalEvents.GetEvent(); } public static void Register() where T : IEasyEvent, new() { mGlobalEvents.AddEvent(); } private Dictionary mTypeEvents = new Dictionary(); public void AddEvent() where T : IEasyEvent, new() { mTypeEvents.Add(typeof(T), new T()); } public T GetEvent() where T : IEasyEvent { IEasyEvent e; if (mTypeEvents.TryGetValue(typeof(T), out e)) { return (T)e; } return default; } public T GetOrAddEvent() where T : IEasyEvent, new() { var eType = typeof(T); if (mTypeEvents.TryGetValue(eType, out var e)) { return (T)e; } var t = new T(); mTypeEvents.Add(eType, t); return t; } } #endregion #if UNITY_EDITOR internal class EditorMenus { [UnityEditor.MenuItem("QFramework/Install QFrameworkWithToolKits")] public static void InstallPackageKit() { Application.OpenURL("https://qframework.cn/qf"); } } #endif }