diff --git a/GFramework.Core.Abstractions/architecture/IArchitecture.cs b/GFramework.Core.Abstractions/architecture/IArchitecture.cs index cc43382..487d323 100644 --- a/GFramework.Core.Abstractions/architecture/IArchitecture.cs +++ b/GFramework.Core.Abstractions/architecture/IArchitecture.cs @@ -15,11 +15,6 @@ public interface IArchitecture : IAsyncInitializable /// IArchitectureContext Context { get; } - /// - /// 获取架构运行时实例 - /// - IArchitectureRuntime Runtime { get; } - /// /// 初始化方法,用于执行对象的初始化操作 /// diff --git a/GFramework.Core.Abstractions/architecture/IArchitectureRuntime.cs b/GFramework.Core.Abstractions/architecture/IArchitectureRuntime.cs deleted file mode 100644 index 7589072..0000000 --- a/GFramework.Core.Abstractions/architecture/IArchitectureRuntime.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using GFramework.Core.Abstractions.command; -using GFramework.Core.Abstractions.events; -using GFramework.Core.Abstractions.query; - -namespace GFramework.Core.Abstractions.architecture; - -/// -/// 架构运行时接口,提供统一的命令、查询、事件操作入口 -/// 负责委托 ArchitectureContext 的能力执行具体操作 -/// -public interface IArchitectureRuntime -{ - /// - /// 发送并执行指定的命令 - /// - /// 命令类型,必须实现ICommand接口 - /// 要执行的命令实例 - void SendCommand(T command) where T : ICommand; - - /// - /// 发送并执行带有返回值的命令 - /// - /// 命令执行结果的类型 - /// 要执行的命令实例 - /// 命令执行的结果 - TResult SendCommand(ICommand command); - - /// - /// 发送并执行查询操作 - /// - /// 查询结果的类型 - /// 要执行的查询实例 - /// 查询的结果 - TResult SendQuery(IQuery query); - - /// - /// 发送无参事件 - /// - /// 事件类型,必须具有无参构造函数 - void SendEvent() where TEvent : new(); - - /// - /// 发送指定的事件实例 - /// - /// 事件类型 - /// 要发送的事件实例 - void SendEvent(TEvent e) where TEvent : class; - - /// - /// 注册事件监听器 - /// - /// 事件类型 - /// 事件触发时的回调方法 - /// 用于取消注册的句柄 - IUnRegister RegisterEvent(Action onEvent); - - /// - /// 取消注册事件监听器 - /// - /// 事件类型 - /// 要取消注册的事件回调方法 - void UnRegisterEvent(Action onEvent); -} \ No newline at end of file diff --git a/GFramework.Core.Abstractions/architecture/IArchitectureServices.cs b/GFramework.Core.Abstractions/architecture/IArchitectureServices.cs index 677f244..2aea8be 100644 --- a/GFramework.Core.Abstractions/architecture/IArchitectureServices.cs +++ b/GFramework.Core.Abstractions/architecture/IArchitectureServices.cs @@ -1,5 +1,7 @@ -using GFramework.Core.Abstractions.events; +using GFramework.Core.Abstractions.command; +using GFramework.Core.Abstractions.events; using GFramework.Core.Abstractions.ioc; +using GFramework.Core.Abstractions.query; using GFramework.Core.Abstractions.rule; namespace GFramework.Core.Abstractions.architecture; @@ -20,4 +22,14 @@ public interface IArchitectureServices : IContextAware /// /// ITypeEventSystem类型的事件系统实例 ITypeEventSystem TypeEventSystem { get; } + + /// + /// 获取命令总线 + /// + public ICommandBus CommandBus { get; } + + /// + /// 获取查询总线 + /// + public IQueryBus QueryBus { get; } } \ No newline at end of file diff --git a/GFramework.Core.Abstractions/command/ICommandBus.cs b/GFramework.Core.Abstractions/command/ICommandBus.cs new file mode 100644 index 0000000..e3f22f0 --- /dev/null +++ b/GFramework.Core.Abstractions/command/ICommandBus.cs @@ -0,0 +1,21 @@ +namespace GFramework.Core.Abstractions.command; + +/// +/// 定义命令总线接口,用于执行各种命令 +/// +public interface ICommandBus +{ + /// + /// 发送并执行一个命令 + /// + /// 要执行的命令对象 + public void Send(ICommand command); + + /// + /// 发送并执行一个带返回值的命令 + /// + /// 命令执行结果的类型 + /// 要执行的带返回值的命令对象 + /// 命令执行的结果 + public TResult Send(ICommand command); +} \ No newline at end of file diff --git a/GFramework.Core.Abstractions/query/IQueryBus.cs b/GFramework.Core.Abstractions/query/IQueryBus.cs new file mode 100644 index 0000000..22d2f66 --- /dev/null +++ b/GFramework.Core.Abstractions/query/IQueryBus.cs @@ -0,0 +1,15 @@ +namespace GFramework.Core.Abstractions.query; + +/// +/// 查询总线接口,用于发送和处理查询请求 +/// +public interface IQueryBus +{ + /// + /// 发送查询请求并返回结果 + /// + /// 查询结果的类型 + /// 要发送的查询对象 + /// 查询结果 + public TResult Send(IQuery query); +} \ No newline at end of file diff --git a/GFramework.Core.Tests/tests/AsyncArchitectureTests.cs b/GFramework.Core.Tests/tests/AsyncArchitectureTests.cs index 205bfaf..3dda32e 100644 --- a/GFramework.Core.Tests/tests/AsyncArchitectureTests.cs +++ b/GFramework.Core.Tests/tests/AsyncArchitectureTests.cs @@ -33,7 +33,6 @@ public class AsyncArchitectureTests : ArchitectureTestsBase // Assert Assert.That(Architecture.InitCalled, Is.True); - Assert.That(Architecture.Runtime, Is.Not.Null); var phase = Architecture.CurrentPhase; Assert.That(phase, Is.EqualTo(ArchitecturePhase.Ready)); diff --git a/GFramework.Core/architecture/Architecture.cs b/GFramework.Core/architecture/Architecture.cs index 5c9e557..4c58c44 100644 --- a/GFramework.Core/architecture/Architecture.cs +++ b/GFramework.Core/architecture/Architecture.cs @@ -1,9 +1,11 @@ using GFramework.Core.Abstractions.architecture; +using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.enums; using GFramework.Core.Abstractions.events; using GFramework.Core.Abstractions.ioc; using GFramework.Core.Abstractions.logging; using GFramework.Core.Abstractions.model; +using GFramework.Core.Abstractions.query; using GFramework.Core.Abstractions.system; using GFramework.Core.Abstractions.utility; using GFramework.Core.events; @@ -55,13 +57,9 @@ public abstract class Architecture( /// private ITypeEventSystem TypeEventSystem => Services.TypeEventSystem; - /// - /// 获取架构运行时实例 - /// - /// - /// 统一的操作入口,负责命令、查询、事件的执行 - /// - public IArchitectureRuntime Runtime { get; private set; } = null!; + private ICommandBus CommandBus => Services.CommandBus; + + private IQueryBus QueryBus => Services.QueryBus; #region Module Management @@ -282,14 +280,16 @@ public abstract class Architecture( { await asyncInit.InitializeAsync(); } - else if (component is IModel model) - { - model.Init(); - } - else if (component is ISystem system) - { - system.Init(); - } + else + switch (component) + { + case IModel model: + model.Init(); + break; + case ISystem system: + system.Init(); + break; + } } /// @@ -306,14 +306,10 @@ public abstract class Architecture( _logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name); // 初始化架构上下文(如果尚未初始化) - _context ??= new ArchitectureContext(Container, TypeEventSystem); + _context ??= new ArchitectureContext(Container, TypeEventSystem, CommandBus, QueryBus); // 将当前架构类型与上下文绑定到游戏上下文 GameContext.Bind(GetType(), _context); - // 创建架构运行时实例 - Runtime = new ArchitectureRuntime(_context); - // 设置上下文中的运行时引用 - ((ArchitectureContext)_context).Runtime = Runtime; // 为服务设置上下文 Services.SetContext(_context); diff --git a/GFramework.Core/architecture/ArchitectureContext.cs b/GFramework.Core/architecture/ArchitectureContext.cs index 191b456..606a0a3 100644 --- a/GFramework.Core/architecture/ArchitectureContext.cs +++ b/GFramework.Core/architecture/ArchitectureContext.cs @@ -14,16 +14,18 @@ namespace GFramework.Core.architecture; /// public class ArchitectureContext( IIocContainer container, - ITypeEventSystem typeEventSystem) + ITypeEventSystem typeEventSystem, + ICommandBus commandBus, + IQueryBus queryBus) : IArchitectureContext { + private readonly ICommandBus _commandBus = commandBus ?? throw new ArgumentNullException(nameof(commandBus)); private readonly IIocContainer _container = container ?? throw new ArgumentNullException(nameof(container)); + private readonly IQueryBus _queryBus = queryBus ?? throw new ArgumentNullException(nameof(queryBus)); private readonly ITypeEventSystem _typeEventSystem = typeEventSystem ?? throw new ArgumentNullException(nameof(typeEventSystem)); - internal IArchitectureRuntime Runtime { get; set; } = null!; - #region Query Execution /// @@ -34,7 +36,7 @@ public class ArchitectureContext( /// 查询结果 public TResult SendQuery(IQuery query) { - return query == null ? throw new ArgumentNullException(nameof(query)) : Runtime.SendQuery(query); + return query == null ? throw new ArgumentNullException(nameof(query)) : _queryBus.Send(query); } #endregion @@ -76,17 +78,17 @@ public class ArchitectureContext( #region Command Execution /// - /// 发送一个无返回结果的命令 + /// 发送一个命令请求 /// /// 要发送的命令 public void SendCommand(ICommand command) { ArgumentNullException.ThrowIfNull(command); - Runtime.SendCommand(command); + _commandBus.Send(command); } /// - /// 发送一个带返回值的命令 + /// 发送一个带返回值的命令请求 /// /// 命令执行结果类型 /// 要发送的命令 @@ -94,7 +96,7 @@ public class ArchitectureContext( public TResult SendCommand(ICommand command) { ArgumentNullException.ThrowIfNull(command); - return Runtime.SendCommand(command); + return _commandBus.Send(command); } #endregion @@ -117,7 +119,7 @@ public class ArchitectureContext( /// 事件参数 public void SendEvent(TEvent e) where TEvent : class { - if (e == null) throw new ArgumentNullException(nameof(e)); + ArgumentNullException.ThrowIfNull(e); _typeEventSystem.Send(e); } diff --git a/GFramework.Core/architecture/ArchitectureRuntime.cs b/GFramework.Core/architecture/ArchitectureRuntime.cs deleted file mode 100644 index 5d368d8..0000000 --- a/GFramework.Core/architecture/ArchitectureRuntime.cs +++ /dev/null @@ -1,98 +0,0 @@ -using GFramework.Core.Abstractions.architecture; -using GFramework.Core.Abstractions.command; -using GFramework.Core.Abstractions.events; -using GFramework.Core.Abstractions.query; - -namespace GFramework.Core.architecture; - -/// -/// 架构运行时默认实现,委托 ArchitectureContext 执行具体操作 -/// -public class ArchitectureRuntime(IArchitectureContext context) : IArchitectureRuntime -{ - private readonly IArchitectureContext _context = context ?? throw new ArgumentNullException(nameof(context)); - - #region Query Execution - - /// - /// 发起一次查询请求并获得其结果 - /// - /// 查询结果的数据类型 - /// 要发起的查询对象 - /// 查询得到的结果数据 - public TResult SendQuery(IQuery query) - { - return _context.SendQuery(query); - } - - #endregion - - #region Command Execution - - /// - /// 发送一个无返回结果的命令请求 - /// - /// 命令的具体类型 - /// 要发送的命令对象 - public void SendCommand(TCommand command) where TCommand : ICommand - { - _context.SendCommand(command); - } - - /// - /// 发送一个带返回结果的命令请求 - /// - /// 命令执行后的返回值类型 - /// 要发送的命令对象 - /// 命令执行的结果 - public TResult SendCommand(ICommand command) - { - return _context.SendCommand(command); - } - - #endregion - - #region Event Management - - /// - /// 发布一个默认构造的新事件对象 - /// - /// 事件类型 - public void SendEvent() where TEvent : new() - { - _context.SendEvent(); - } - - /// - /// 发布一个具体的事件对象 - /// - /// 事件类型 - /// 要发布的事件实例 - public void SendEvent(TEvent e) where TEvent : class - { - _context.SendEvent(e); - } - - /// - /// 订阅某个特定类型的事件 - /// - /// 事件类型 - /// 当事件发生时触发的动作 - /// 可用于取消订阅的对象 - public IUnRegister RegisterEvent(Action onEvent) - { - return _context.RegisterEvent(onEvent); - } - - /// - /// 取消对某类型事件的监听 - /// - /// 事件类型 - /// 之前绑定的事件处理器 - public void UnRegisterEvent(Action onEvent) - { - _context.UnRegisterEvent(onEvent); - } - - #endregion -} \ No newline at end of file diff --git a/GFramework.Core/architecture/ArchitectureServices.cs b/GFramework.Core/architecture/ArchitectureServices.cs index 7b29217..6119004 100644 --- a/GFramework.Core/architecture/ArchitectureServices.cs +++ b/GFramework.Core/architecture/ArchitectureServices.cs @@ -1,23 +1,56 @@ using GFramework.Core.Abstractions.architecture; +using GFramework.Core.Abstractions.command; using GFramework.Core.Abstractions.events; using GFramework.Core.Abstractions.ioc; +using GFramework.Core.Abstractions.query; +using GFramework.Core.command; using GFramework.Core.events; using GFramework.Core.ioc; +using GFramework.Core.query; namespace GFramework.Core.architecture; +/// +/// 架构服务类,提供依赖注入容器、事件系统、命令总线和查询总线等核心服务 +/// public class ArchitectureServices : IArchitectureServices { private IArchitectureContext _context = null!; + + /// + /// 获取依赖注入容器 + /// public IIocContainer Container { get; } = new IocContainer(); + + /// + /// 获取类型事件系统 + /// public ITypeEventSystem TypeEventSystem { get; } = new TypeEventSystem(); + /// + /// 获取命令总线 + /// + public ICommandBus CommandBus { get; } = new CommandBus(); + + /// + /// 获取查询总线 + /// + public IQueryBus QueryBus { get; } = new QueryBus(); + + /// + /// 设置架构上下文 + /// + /// 架构上下文对象 public void SetContext(IArchitectureContext context) { _context = context; Container.SetContext(context); } + /// + /// 获取架构上下文 + /// + /// 架构上下文对象 public IArchitectureContext GetContext() { return _context; diff --git a/GFramework.Core/architecture/GameContext.cs b/GFramework.Core/architecture/GameContext.cs index 1c26c91..a73b653 100644 --- a/GFramework.Core/architecture/GameContext.cs +++ b/GFramework.Core/architecture/GameContext.cs @@ -38,7 +38,7 @@ public static class GameContext /// /// 返回字典中的第一个架构上下文实例 /// 当字典为空时抛出 - public static IArchitectureContext GetFirstArchitecture() + public static IArchitectureContext GetFirstArchitectureContext() { return ArchitectureDictionary.Values.First(); } diff --git a/GFramework.Core/command/CommandBus.cs b/GFramework.Core/command/CommandBus.cs new file mode 100644 index 0000000..60faa7b --- /dev/null +++ b/GFramework.Core/command/CommandBus.cs @@ -0,0 +1,35 @@ +using GFramework.Core.Abstractions.command; + +namespace GFramework.Core.command; + +/// +/// 命令总线实现类,用于发送和执行命令 +/// +public sealed class CommandBus : ICommandBus +{ + /// + /// 发送并执行无返回值的命令 + /// + /// 要执行的命令对象,不能为空 + /// 当command参数为null时抛出 + public void Send(ICommand command) + { + ArgumentNullException.ThrowIfNull(command); + + command.Execute(); + } + + /// + /// 发送并执行有返回值的命令 + /// + /// 命令执行结果的类型 + /// 要执行的命令对象,不能为空 + /// 命令执行的结果 + /// 当command参数为null时抛出 + public TResult Send(ICommand command) + { + ArgumentNullException.ThrowIfNull(command); + + return command.Execute(); + } +} \ No newline at end of file diff --git a/GFramework.Core/query/QueryBus.cs b/GFramework.Core/query/QueryBus.cs new file mode 100644 index 0000000..34cfa58 --- /dev/null +++ b/GFramework.Core/query/QueryBus.cs @@ -0,0 +1,23 @@ +using GFramework.Core.Abstractions.query; + +namespace GFramework.Core.query; + +/// +/// 查询总线实现,负责执行查询并返回结果 +/// +public sealed class QueryBus : IQueryBus +{ + /// + /// 执行指定的查询并返回结果 + /// + /// 查询结果的类型 + /// 要执行的查询对象 + /// 查询执行结果 + public TResult Send(IQuery query) + { + // 验证查询参数不为null + ArgumentNullException.ThrowIfNull(query); + + return query.Do(); + } +} \ No newline at end of file diff --git a/GFramework.Core/rule/ContextAwareBase.cs b/GFramework.Core/rule/ContextAwareBase.cs index b436bda..cba9784 100644 --- a/GFramework.Core/rule/ContextAwareBase.cs +++ b/GFramework.Core/rule/ContextAwareBase.cs @@ -1,5 +1,6 @@ using GFramework.Core.Abstractions.architecture; using GFramework.Core.Abstractions.rule; +using GFramework.Core.architecture; namespace GFramework.Core.rule; @@ -11,7 +12,7 @@ public abstract class ContextAwareBase : IContextAware /// /// 获取当前实例的架构上下文 /// - protected IArchitectureContext Context { get; set; } = null!; + protected IArchitectureContext? Context { get; set; } /// /// 设置架构上下文的实现方法,由框架调用 @@ -29,6 +30,7 @@ public abstract class ContextAwareBase : IContextAware /// 当前架构上下文对象 IArchitectureContext IContextAware.GetContext() { + Context ??= GameContext.GetFirstArchitectureContext(); return Context; } diff --git a/GFramework.Godot/assets/AbstractResourceFactorySystem.cs b/GFramework.Godot/assets/AbstractResourceFactorySystem.cs index 9c1ac24..fe6ebd3 100644 --- a/GFramework.Godot/assets/AbstractResourceFactorySystem.cs +++ b/GFramework.Godot/assets/AbstractResourceFactorySystem.cs @@ -1,4 +1,5 @@ using GFramework.Core.Abstractions.enums; +using GFramework.Core.extensions; using GFramework.Core.system; using GFramework.Game.Abstractions.assets; using GFramework.Godot.Abstractions.assets; @@ -63,8 +64,8 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF protected override void OnInit() { _registry = new ResourceFactory.Registry(); - _resourceLoadSystem = Context.GetSystem(); - _assetCatalogSystem = Context.GetSystem(); + _assetCatalogSystem = this.GetSystem(); + _assetCatalogSystem = this.GetSystem(); } /// diff --git a/GFramework.Godot/system/AbstractAudioManagerSystem.cs b/GFramework.Godot/system/AbstractAudioManagerSystem.cs index 288b072..6a77f99 100644 --- a/GFramework.Godot/system/AbstractAudioManagerSystem.cs +++ b/GFramework.Godot/system/AbstractAudioManagerSystem.cs @@ -1,3 +1,4 @@ +using GFramework.Core.extensions; using GFramework.Core.system; using GFramework.Game.Abstractions.assets; using GFramework.Godot.Abstractions.assets; @@ -431,9 +432,9 @@ public abstract class AbstractAudioManagerSystem : AbstractSystem, IAudioManager protected override void OnInit() { // 获取依赖的系统 - ResourceLoadSystem = Context.GetSystem(); - AssetCatalogSystem = Context.GetSystem(); - ResourceFactorySystem = Context.GetSystem(); + ResourceLoadSystem = this.GetSystem(); + AssetCatalogSystem = this.GetSystem(); + ResourceFactorySystem = this.GetSystem(); // 初始化背景音乐播放器 MusicPlayer = new AudioStreamPlayer(); diff --git a/GFramework.SourceGenerators.Tests/rule/ContextAwareGeneratorSnapshotTests.cs b/GFramework.SourceGenerators.Tests/rule/ContextAwareGeneratorSnapshotTests.cs index 1ea9d9b..aa43434 100644 --- a/GFramework.SourceGenerators.Tests/rule/ContextAwareGeneratorSnapshotTests.cs +++ b/GFramework.SourceGenerators.Tests/rule/ContextAwareGeneratorSnapshotTests.cs @@ -64,7 +64,7 @@ public class ContextAwareGeneratorSnapshotTests /// /// 返回字典中的第一个架构上下文实例 /// 当字典为空时抛出 - public static IArchitectureContext GetFirstArchitecture() + public static IArchitectureContext GetFirstArchitectureContext() { return null; } diff --git a/GFramework.SourceGenerators/rule/ContextAwareGenerator.cs b/GFramework.SourceGenerators/rule/ContextAwareGenerator.cs index 4caffa4..c1b1998 100644 --- a/GFramework.SourceGenerators/rule/ContextAwareGenerator.cs +++ b/GFramework.SourceGenerators/rule/ContextAwareGenerator.cs @@ -140,7 +140,7 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase sb.AppendLine(" if (_context == null)"); sb.AppendLine(" {"); sb.AppendLine( - " _context = global::GFramework.Core.architecture.GameContext.GetFirstArchitecture();"); + " _context = global::GFramework.Core.architecture.GameContext.GetFirstArchitectureContext();"); sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" return _context;");