refactor(architecture): 重构架构上下文和服务初始化逻辑

- 移除 Architecture 类中的命令总线、查询总线和异步查询总线属性
- 修改 ArchitectureContext 构造函数,仅接收容器参数并实现服务缓存机制
- 添加 GetService 方法用于获取指定类型的服务实例
- 更新所有查询和命令方法使用服务缓存机制
- 修改 ArchitectureServices 构造函数初始化逻辑,将服务注册到容器
- 更新相关测试类中的上下文初始化方式
- 在 GameContext 和相关测试类中实现 GetService 方法
This commit is contained in:
GeWuYou 2026-01-18 22:26:02 +08:00
parent 241efa0363
commit 825a026c8e
11 changed files with 174 additions and 190 deletions

View File

@ -15,6 +15,13 @@ namespace GFramework.Core.Abstractions.architecture;
/// </summary>
public interface IArchitectureContext
{
/// <summary>
/// 获取指定类型的服务实例
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <returns>服务实例如果不存在则返回null</returns>
TService? GetService<TService>() where TService : class;
/// <summary>
/// 获取指定类型的系统实例
/// </summary>

View File

@ -57,12 +57,21 @@ public class ArchitectureContextTests
loggerField?.SetValue(_container,
LoggerFactoryResolver.Provider.CreateLogger(nameof(ArchitectureContextTests)));
// 创建服务实例
_eventBus = new EventBus();
_commandBus = new CommandBus();
_queryBus = new QueryBus();
_asyncQueryBus = new AsyncQueryBus();
_environment = new DefaultEnvironment();
_context = new ArchitectureContext(_container, _eventBus, _commandBus, _queryBus, _environment, _asyncQueryBus);
// 将服务注册到容器
_container.RegisterPlurality(_eventBus);
_container.RegisterPlurality(_commandBus);
_container.RegisterPlurality(_queryBus);
_container.RegisterPlurality(_asyncQueryBus);
_container.RegisterPlurality(_environment);
_context = new ArchitectureContext(_container);
}
private ArchitectureContext? _context;
@ -79,10 +88,7 @@ public class ArchitectureContextTests
[Test]
public void Constructor_Should_NotThrow_When_AllParameters_AreValid()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, _environment!,
_asyncQueryBus!),
Throws.Nothing);
Assert.That(() => new ArchitectureContext(_container!), Throws.Nothing);
}
/// <summary>
@ -91,53 +97,7 @@ public class ArchitectureContextTests
[Test]
public void Constructor_Should_Throw_When_Container_IsNull()
{
Assert.That(
() => new ArchitectureContext(null!, _eventBus!, _commandBus!, _queryBus!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException);
}
/// <summary>
/// 测试构造函数在 eventBus 为 null 时应抛出 ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_Throw_When_EventBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, null!, _commandBus!, _queryBus!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException);
}
/// <summary>
/// 测试构造函数在 commandBus 为 null 时应抛出 ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_Throw_When_CommandBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, null!, _queryBus!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException);
}
/// <summary>
/// 测试构造函数在 queryBus 为 null 时应抛出 ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_Throw_When_QueryBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, null!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException);
}
/// <summary>
/// 测试构造函数在 environment 为 null 时应抛出 ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_Throw_When_Environment_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, null!, _asyncQueryBus!),
Throws.ArgumentNullException);
Assert.That(() => new ArchitectureContext(null!), Throws.ArgumentNullException);
}
/// <summary>
@ -146,55 +106,10 @@ public class ArchitectureContextTests
[Test]
public void Constructor_Should_ThrowArgumentNullException_When_Container_IsNull()
{
Assert.That(
() => new ArchitectureContext(null!, _eventBus!, _commandBus!, _queryBus!, _environment!, _asyncQueryBus!),
Assert.That(() => new ArchitectureContext(null!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("container"));
}
/// <summary>
/// 测试构造函数在EventBus为null时应抛出ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_ThrowArgumentNullException_When_EventBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, null!, _commandBus!, _queryBus!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("eventBus"));
}
/// <summary>
/// 测试构造函数在CommandBus为null时应抛出ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_ThrowArgumentNullException_When_CommandBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, null!, _queryBus!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("commandBus"));
}
/// <summary>
/// 测试构造函数在QueryBus为null时应抛出ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_ThrowArgumentNullException_When_QueryBus_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, null!, _environment!, _asyncQueryBus!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("queryBus"));
}
/// <summary>
/// 测试构造函数在Environment为null时应抛出ArgumentNullException
/// </summary>
[Test]
public void Constructor_Should_ThrowArgumentNullException_When_Environment_IsNull()
{
Assert.That(
() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, null!, _asyncQueryBus!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("environment"));
}
/// <summary>
/// 测试SendQuery方法在查询有效时返回正确结果
/// </summary>
@ -439,14 +354,6 @@ public class TestUtilityV2 : IUtility
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public void Init()
{
}
public void Destroy()
{
}
}
public class TestQueryV2 : IQuery<int>

View File

@ -227,6 +227,7 @@ public class TestArchitectureContextV3 : IArchitectureContext
public ICommandBus CommandBus => new CommandBus();
public IQueryBus QueryBus => new QueryBus();
public TService? GetService<TService>() where TService : class => _container.Get<TService>();
public TModel? GetModel<TModel>() where TModel : class, IModel => _container.Get<TModel>();
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem => _container.Get<TSystem>();
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility => _container.Get<TUtility>();

View File

@ -256,6 +256,13 @@ public class TestArchitectureContext : IArchitectureContext
/// </summary>
public IEnvironment Environment => new DefaultEnvironment();
/// <summary>
/// 获取指定类型的服务
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <returns>服务实例或null</returns>
public TService? GetService<TService>() where TService : class => _container.Get<TService>();
/// <summary>
/// 获取指定类型的模型
/// </summary>

View File

@ -33,13 +33,12 @@ public class AbstractAsyncCommandTests
public void SetUp()
{
_container = new IocContainer();
_context = new ArchitectureContext(
_container,
new EventBus(),
new CommandBus(),
new QueryBus(),
new DefaultEnvironment(),
new AsyncQueryBus());
_container.RegisterPlurality(new EventBus());
_container.RegisterPlurality(new CommandBus());
_container.RegisterPlurality(new QueryBus());
_container.RegisterPlurality(new DefaultEnvironment());
_container.RegisterPlurality(new AsyncQueryBus());
_context = new ArchitectureContext(_container);
}
private ArchitectureContext _context = null!;

View File

@ -31,13 +31,12 @@ public class AbstractAsyncQueryTests
public void SetUp()
{
_container = new IocContainer();
_context = new ArchitectureContext(
_container,
new EventBus(),
new CommandBus(),
new QueryBus(),
new DefaultEnvironment(),
new AsyncQueryBus());
_container.RegisterPlurality(new EventBus());
_container.RegisterPlurality(new CommandBus());
_container.RegisterPlurality(new QueryBus());
_container.RegisterPlurality(new DefaultEnvironment());
_container.RegisterPlurality(new AsyncQueryBus());
_context = new ArchitectureContext(_container);
}
private ArchitectureContext _context = null!;

View File

@ -1,3 +1,4 @@
using System.Reflection;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.state;
using GFramework.Core.Abstractions.system;
@ -6,6 +7,7 @@ using GFramework.Core.command;
using GFramework.Core.environment;
using GFramework.Core.events;
using GFramework.Core.ioc;
using GFramework.Core.logging;
using GFramework.Core.query;
using GFramework.Core.state;
using NUnit.Framework;
@ -35,14 +37,25 @@ public class StateMachineSystemTests
[SetUp]
public void SetUp()
{
// 初始化 LoggerFactoryResolver 以支持 IocContainer
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
_eventBus = new EventBus();
_context = new ArchitectureContext(
new IocContainer(),
_eventBus,
new CommandBus(),
new QueryBus(),
new DefaultEnvironment(),
new AsyncQueryBus());
var container = new IocContainer();
// 直接初始化 logger 字段
var loggerField = typeof(IocContainer).GetField("_logger",
BindingFlags.NonPublic | BindingFlags.Instance);
loggerField?.SetValue(container,
LoggerFactoryResolver.Provider.CreateLogger(nameof(StateMachineSystemTests)));
container.RegisterPlurality(_eventBus);
container.RegisterPlurality(new CommandBus());
container.RegisterPlurality(new QueryBus());
container.RegisterPlurality(new DefaultEnvironment());
container.RegisterPlurality(new AsyncQueryBus());
_context = new ArchitectureContext(container);
_stateMachine = new TestStateMachineSystemV5();
_stateMachine.SetContext(_context);

View File

@ -31,13 +31,12 @@ public class AbstractContextUtilityTests
public void SetUp()
{
_container = new IocContainer();
_context = new ArchitectureContext(
_container,
new EventBus(),
new CommandBus(),
new QueryBus(),
new DefaultEnvironment(),
new AsyncQueryBus());
_container.RegisterPlurality(new EventBus());
_container.RegisterPlurality(new CommandBus());
_container.RegisterPlurality(new QueryBus());
_container.RegisterPlurality(new DefaultEnvironment());
_container.RegisterPlurality(new AsyncQueryBus());
_context = new ArchitectureContext(_container);
}
private ArchitectureContext _context = null!;

View File

@ -1,5 +1,4 @@
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.environment;
using GFramework.Core.Abstractions.events;
@ -7,14 +6,12 @@ using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.lifecycle;
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.environment;
using GFramework.Core.events;
using GFramework.Core.extensions;
using GFramework.Core.logging;
using IAsyncQueryBus = GFramework.Core.Abstractions.query.IAsyncQueryBus;
using IDisposable = GFramework.Core.Abstractions.lifecycle.IDisposable;
namespace GFramework.Core.architecture;
@ -79,21 +76,6 @@ public abstract class Architecture(
/// </summary>
private IEventBus EventBus => Services.EventBus;
/// <summary>
/// 获取命令总线
/// </summary>
private ICommandBus CommandBus => Services.CommandBus;
/// <summary>
/// 获取查询总线
/// </summary>
private IQueryBus QueryBus => Services.QueryBus;
/// <summary>
/// 获取异步查询总线
/// </summary>
private IAsyncQueryBus AsyncQueryBus => Services.AsyncQueryBus;
/// <summary>
/// 当前架构的阶段
/// </summary>
@ -553,8 +535,12 @@ public abstract class Architecture(
_logger = LoggerFactoryResolver.Provider.CreateLogger(GetType().Name);
Environment.Initialize();
// 将 Environment 注册到容器(如果尚未注册)
if (!Container.Contains<IEnvironment>())
Container.RegisterPlurality(Environment);
// 初始化架构上下文(如果尚未初始化)
_context ??= new ArchitectureContext(Container, EventBus, CommandBus, QueryBus, Environment, AsyncQueryBus);
_context ??= new ArchitectureContext(Container);
GameContext.Bind(GetType(), _context);
// 为服务设置上下文

View File

@ -7,34 +7,38 @@ using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.query;
using GFramework.Core.Abstractions.system;
using GFramework.Core.Abstractions.utility;
using IAsyncQueryBus = GFramework.Core.Abstractions.query.IAsyncQueryBus;
namespace GFramework.Core.architecture;
/// <summary>
/// 架构上下文类,提供对系统、模型、工具等组件的访问以及命令、查询、事件的执行管理
/// </summary>
public class ArchitectureContext(
IIocContainer container,
IEventBus eventBus,
ICommandBus commandBus,
IQueryBus queryBus,
IEnvironment environment,
IAsyncQueryBus asyncQueryBus)
: IArchitectureContext
public class ArchitectureContext : IArchitectureContext
{
private readonly IAsyncQueryBus _asyncQueryBus =
asyncQueryBus ?? throw new ArgumentNullException(nameof(asyncQueryBus));
private readonly IIocContainer _container;
private readonly Dictionary<Type, object> _serviceCache = new();
private readonly ICommandBus _commandBus = commandBus ?? throw new ArgumentNullException(nameof(commandBus));
private readonly IIocContainer _container = container ?? throw new ArgumentNullException(nameof(container));
public ArchitectureContext(IIocContainer container)
{
_container = container ?? throw new ArgumentNullException(nameof(container));
}
private readonly IEnvironment _environment = environment ?? throw new ArgumentNullException(nameof(environment));
public TService? GetService<TService>() where TService : class
{
return GetOrCache<TService>();
}
private readonly IEventBus _eventBus =
eventBus ?? throw new ArgumentNullException(nameof(eventBus));
private TService? GetOrCache<TService>() where TService : class
{
if (_serviceCache.TryGetValue(typeof(TService), out var cached))
return (TService)cached;
private readonly IQueryBus _queryBus = queryBus ?? throw new ArgumentNullException(nameof(queryBus));
var service = _container.Get<TService>();
if (service != null)
_serviceCache[typeof(TService)] = service;
return service;
}
#region Query Execution
@ -46,7 +50,10 @@ public class ArchitectureContext(
/// <returns>查询结果</returns>
public TResult SendQuery<TResult>(IQuery<TResult> query)
{
return query == null ? throw new ArgumentNullException(nameof(query)) : _queryBus.Send(query);
if (query == null) throw new ArgumentNullException(nameof(query));
var queryBus = GetOrCache<IQueryBus>();
if (queryBus == null) throw new InvalidOperationException("IQueryBus not registered");
return queryBus.Send(query);
}
/// <summary>
@ -55,9 +62,12 @@ public class ArchitectureContext(
/// <typeparam name="TResult">查询结果类型</typeparam>
/// <param name="query">要发送的异步查询</param>
/// <returns>查询结果</returns>
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
public async Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return query == null ? throw new ArgumentNullException(nameof(query)) : _asyncQueryBus.SendAsync(query);
if (query == null) throw new ArgumentNullException(nameof(query));
var asyncQueryBus = GetOrCache<IAsyncQueryBus>();
if (asyncQueryBus == null) throw new InvalidOperationException("IAsyncQueryBus not registered");
return await asyncQueryBus.SendAsync(query);
}
#endregion
@ -71,7 +81,7 @@ public class ArchitectureContext(
/// <returns>对应的系统实例</returns>
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.Get<TSystem>();
return GetService<TSystem>();
}
/// <summary>
@ -81,7 +91,7 @@ public class ArchitectureContext(
/// <returns>对应的模型实例</returns>
public TModel? GetModel<TModel>() where TModel : class, IModel
{
return _container.Get<TModel>();
return GetService<TModel>();
}
/// <summary>
@ -91,7 +101,7 @@ public class ArchitectureContext(
/// <returns>对应的工具实例</returns>
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.Get<TUtility>();
return GetService<TUtility>();
}
#endregion
@ -105,7 +115,8 @@ public class ArchitectureContext(
public void SendCommand(ICommand command)
{
ArgumentNullException.ThrowIfNull(command);
_commandBus.Send(command);
var commandBus = GetOrCache<ICommandBus>();
commandBus?.Send(command);
}
/// <summary>
@ -117,7 +128,9 @@ public class ArchitectureContext(
public TResult SendCommand<TResult>(ICommand<TResult> command)
{
ArgumentNullException.ThrowIfNull(command);
return _commandBus.Send(command);
var commandBus = GetOrCache<ICommandBus>();
if (commandBus == null) throw new InvalidOperationException("ICommandBus not registered");
return commandBus.Send(command);
}
/// <summary>
@ -127,7 +140,9 @@ public class ArchitectureContext(
public async Task SendCommandAsync(IAsyncCommand command)
{
ArgumentNullException.ThrowIfNull(command);
await _commandBus.SendAsync(command);
var commandBus = GetOrCache<ICommandBus>();
if (commandBus == null) throw new InvalidOperationException("ICommandBus not registered");
await commandBus.SendAsync(command);
}
/// <summary>
@ -139,7 +154,9 @@ public class ArchitectureContext(
public async Task<TResult> SendCommandAsync<TResult>(IAsyncCommand<TResult> command)
{
ArgumentNullException.ThrowIfNull(command);
return await _commandBus.SendAsync(command);
var commandBus = GetOrCache<ICommandBus>();
if (commandBus == null) throw new InvalidOperationException("ICommandBus not registered");
return await commandBus.SendAsync(command);
}
#endregion
@ -152,7 +169,8 @@ public class ArchitectureContext(
/// <typeparam name="TEvent">事件类型</typeparam>
public void SendEvent<TEvent>() where TEvent : new()
{
_eventBus.Send<TEvent>();
var eventBus = GetOrCache<IEventBus>();
eventBus?.Send<TEvent>();
}
/// <summary>
@ -163,7 +181,8 @@ public class ArchitectureContext(
public void SendEvent<TEvent>(TEvent e) where TEvent : class
{
ArgumentNullException.ThrowIfNull(e);
_eventBus.Send(e);
var eventBus = GetOrCache<IEventBus>();
eventBus?.Send(e);
}
/// <summary>
@ -174,7 +193,10 @@ public class ArchitectureContext(
/// <returns>事件注销接口</returns>
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
return handler == null ? throw new ArgumentNullException(nameof(handler)) : _eventBus.Register(handler);
ArgumentNullException.ThrowIfNull(handler);
var eventBus = GetOrCache<IEventBus>();
if (eventBus == null) throw new InvalidOperationException("IEventBus not registered");
return eventBus.Register(handler);
}
/// <summary>
@ -185,7 +207,8 @@ public class ArchitectureContext(
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
ArgumentNullException.ThrowIfNull(onEvent);
_eventBus.UnRegister(onEvent);
var eventBus = GetOrCache<IEventBus>();
eventBus?.UnRegister(onEvent);
}
/// <summary>
@ -194,7 +217,8 @@ public class ArchitectureContext(
/// <returns>环境对象实例</returns>
public IEnvironment GetEnvironment()
{
return _environment;
var environment = GetOrCache<IEnvironment>();
return environment ?? throw new InvalidOperationException("IEnvironment not registered");
}
#endregion

View File

@ -16,32 +16,74 @@ namespace GFramework.Core.architecture;
/// </summary>
public class ArchitectureServices : IArchitectureServices
{
/// <summary>
/// 异步查询总线实例
/// </summary>
private readonly IAsyncQueryBus _asyncQueryBus;
/// <summary>
/// 命令总线实例
/// </summary>
private readonly ICommandBus _commandBus;
private readonly IIocContainer _container;
/// <summary>
/// 事件总线实例
/// </summary>
private readonly IEventBus _eventBus;
/// <summary>
/// 查询总线实例
/// </summary>
private readonly IQueryBus _queryBus;
private IArchitectureContext _context = null!;
/// <summary>
/// 构造函数,初始化架构服务
/// </summary>
public ArchitectureServices()
{
_container = new IocContainer();
// 创建服务实例
_eventBus = new EventBus();
_commandBus = new CommandBus();
_queryBus = new QueryBus();
_asyncQueryBus = new AsyncQueryBus();
// 将服务注册到容器
_container.RegisterPlurality(_eventBus);
_container.RegisterPlurality(_commandBus);
_container.RegisterPlurality(_queryBus);
_container.RegisterPlurality(_asyncQueryBus);
}
/// <summary>
/// 获取依赖注入容器
/// </summary>
public IIocContainer Container { get; } = new IocContainer();
public IIocContainer Container => _container;
/// <summary>
/// 获取类型事件系统
/// </summary>
public IEventBus EventBus { get; } = new EventBus();
public IEventBus EventBus => _eventBus;
/// <summary>
/// 获取命令总线
/// </summary>
public ICommandBus CommandBus { get; } = new CommandBus();
public ICommandBus CommandBus => _commandBus;
/// <summary>
/// 获取查询总线
/// </summary>
public IQueryBus QueryBus { get; } = new QueryBus();
public IQueryBus QueryBus => _queryBus;
/// <summary>
/// 获取异步查询总线
/// </summary>
public IAsyncQueryBus AsyncQueryBus { get; } = new AsyncQueryBus();
public IAsyncQueryBus AsyncQueryBus => _asyncQueryBus;
/// <summary>
/// 设置架构上下文