refactor(arch): 重构架构组件注册机制

- 将组件注册逻辑提取到独立的 ArchitectureComponentRegistry 类中
- 实现 ArchitectureComponentActivator 来支持注册阶段实例化组件
- 更新系统和模型注册文档说明,明确在注册阶段创建实例并参与初始化
- 修复类型注册在架构准备就绪后的行为一致性问题
- 添加完整的组件注册行为测试覆盖实例注册、工厂注册和生命周期管理
- 优化依赖注入解析机制,支持构造函数依赖和单例缓存
This commit is contained in:
GeWuYou 2026-04-05 11:01:50 +08:00
parent 01dc1523a5
commit bb2b3a0c60
4 changed files with 281 additions and 35 deletions

View File

@ -122,6 +122,62 @@ public class ArchitectureComponentRegistryBehaviorTests
await architecture.DestroyAsync();
}
/// <summary>
/// 验证系统类型注册会在初始化期间物化实例、注入构造函数依赖并执行创建回调。
/// </summary>
[Test]
public async Task RegisterSystem_Type_Should_Create_Instance_During_Initialization()
{
var dependency = new ConstructorDependency("system-dependency");
FactoryCreatedSystem? callbackInstance = null;
var architecture = new RegistryTestArchitecture(
target => target.RegisterSystem<FactoryCreatedSystem>(created => callbackInstance = created),
services => services.AddSingleton(dependency));
await architecture.InitializeAsync();
var resolved = architecture.Context.GetSystem<FactoryCreatedSystem>();
Assert.Multiple(() =>
{
Assert.That(callbackInstance, Is.Not.Null);
Assert.That(resolved, Is.SameAs(callbackInstance));
Assert.That(resolved.Dependency, Is.SameAs(dependency));
Assert.That(resolved.GetContext(), Is.SameAs(architecture.Context));
Assert.That(resolved.InitializeCallCount, Is.EqualTo(1));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证模型类型注册会在初始化期间物化实例、注入构造函数依赖并执行创建回调。
/// </summary>
[Test]
public async Task RegisterModel_Type_Should_Create_Instance_During_Initialization()
{
var dependency = new ConstructorDependency("model-dependency");
FactoryCreatedModel? callbackInstance = null;
var architecture = new RegistryTestArchitecture(
target => target.RegisterModel<FactoryCreatedModel>(created => callbackInstance = created),
services => services.AddSingleton(dependency));
await architecture.InitializeAsync();
var resolved = architecture.Context.GetModel<FactoryCreatedModel>();
Assert.Multiple(() =>
{
Assert.That(callbackInstance, Is.Not.Null);
Assert.That(resolved, Is.SameAs(callbackInstance));
Assert.That(resolved.Dependency, Is.SameAs(dependency));
Assert.That(resolved.GetContext(), Is.SameAs(architecture.Context));
Assert.That(resolved.InitializeCallCount, Is.EqualTo(1));
});
await architecture.DestroyAsync();
}
/// <summary>
/// 验证 Ready 阶段后不允许继续注册 Utility保持与系统和模型一致的约束。
/// </summary>
@ -142,14 +198,35 @@ public class ArchitectureComponentRegistryBehaviorTests
/// <summary>
/// 用于测试组件注册行为的最小架构实现。
/// </summary>
private sealed class RegistryTestArchitecture(Action<RegistryTestArchitecture> registrationAction) : Architecture
private sealed class RegistryTestArchitecture : Architecture
{
private readonly Action<IServiceCollection>? _configurator;
private readonly Action<RegistryTestArchitecture> _registrationAction;
/// <summary>
/// 创建一个可选地附带服务配置逻辑的测试架构。
/// </summary>
/// <param name="registrationAction">初始化阶段执行的组件注册逻辑。</param>
/// <param name="configurator">初始化前执行的服务配置逻辑。</param>
public RegistryTestArchitecture(
Action<RegistryTestArchitecture> registrationAction,
Action<IServiceCollection>? configurator = null)
{
_registrationAction = registrationAction;
_configurator = configurator;
}
/// <summary>
/// 返回测试注入的服务配置逻辑。
/// </summary>
public override Action<IServiceCollection>? Configurator => _configurator;
/// <summary>
/// 在初始化阶段执行测试注入的注册逻辑。
/// </summary>
protected override void OnInitialize()
{
registrationAction(this);
_registrationAction(this);
}
}
@ -303,4 +380,93 @@ public class ArchitectureComponentRegistryBehaviorTests
private sealed class FactoryCreatedUtility : IUtility
{
}
/// <summary>
/// 用于验证构造函数依赖注入的简单依赖对象。
/// </summary>
private sealed class ConstructorDependency(string name)
{
/// <summary>
/// 获取依赖对象名称。
/// </summary>
public string Name { get; } = name;
}
/// <summary>
/// 用于验证系统类型注册路径的工厂创建系统。
/// </summary>
private sealed class FactoryCreatedSystem(ConstructorDependency dependency) : ISystem
{
private IArchitectureContext _context = null!;
/// <summary>
/// 获取构造函数注入的依赖对象。
/// </summary>
public ConstructorDependency Dependency { get; } = dependency;
/// <summary>
/// 获取初始化调用次数。
/// </summary>
public int InitializeCallCount { get; private set; }
public void Initialize()
{
InitializeCallCount++;
}
public void Destroy()
{
}
public void OnArchitecturePhase(ArchitecturePhase phase)
{
}
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
/// <summary>
/// 用于验证模型类型注册路径的工厂创建模型。
/// </summary>
private sealed class FactoryCreatedModel(ConstructorDependency dependency) : IModel
{
private IArchitectureContext _context = null!;
/// <summary>
/// 获取构造函数注入的依赖对象。
/// </summary>
public ConstructorDependency Dependency { get; } = dependency;
/// <summary>
/// 获取初始化调用次数。
/// </summary>
public int InitializeCallCount { get; private set; }
public void Initialize()
{
InitializeCallCount++;
}
public void OnArchitecturePhase(ArchitecturePhase phase)
{
}
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
}

View File

@ -7,7 +7,6 @@ using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Environment;
using GFramework.Core.Logging;
using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.Architectures;
@ -182,7 +181,7 @@ public abstract class Architecture : IArchitecture
}
/// <summary>
/// 注册系统类型,由 DI 容器自动创建实例
/// 注册系统类型,由当前服务集合自动创建实例并接入本轮初始化
/// </summary>
/// <typeparam name="T">系统类型</typeparam>
/// <param name="onCreated">可选的实例创建后回调</param>
@ -203,7 +202,7 @@ public abstract class Architecture : IArchitecture
}
/// <summary>
/// 注册模型类型,由 DI 容器自动创建实例
/// 注册模型类型,由当前服务集合自动创建实例并接入本轮初始化
/// </summary>
/// <typeparam name="T">模型类型</typeparam>
/// <param name="onCreated">可选的实例创建后回调</param>

View File

@ -0,0 +1,94 @@
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Logging;
namespace GFramework.Core.Architectures;
/// <summary>
/// 为架构组件的类型注册路径提供实例创建能力。
/// 该类型在容器冻结前基于当前服务集合和已注册实例进行激活,
/// 使 <see cref="ArchitectureComponentRegistry" /> 可以在注册阶段就物化 System / Model
/// 避免它们在 Ready 之后首次解析时才参与生命周期而导致状态不一致。
/// </summary>
internal sealed class ArchitectureComponentActivator(
IIocContainer container,
ILogger logger)
{
/// <summary>
/// 根据当前容器状态创建组件实例。
/// 激活过程优先复用已经注册到容器中的实例,再按服务描述解析实现类型或工厂方法,
/// 以兼容构造函数依赖于框架服务、用户实例服务和先前注册组件的场景。
/// </summary>
/// <typeparam name="TComponent">要创建的组件类型。</typeparam>
/// <returns>创建完成的组件实例。</returns>
public TComponent CreateInstance<TComponent>() where TComponent : class
{
var activationProvider = new RegistrationServiceProvider(container, logger);
return ActivatorUtilities.CreateInstance<TComponent>(activationProvider);
}
/// <summary>
/// 面向组件注册的轻量级服务提供者。
/// 该实现只覆盖预冻结阶段需要的解析能力,避免引入完整容器冻结过程。
/// </summary>
private sealed class RegistrationServiceProvider(
IIocContainer container,
ILogger logger) : IServiceProvider
{
private readonly Dictionary<Type, object?> _singletonCache = [];
/// <summary>
/// 从当前服务集合中解析指定类型的服务。
/// 解析顺序为:已注册实例 → 服务描述实例/工厂/实现类型 → 可直接实例化的具体类型。
/// </summary>
/// <param name="serviceType">请求解析的服务类型。</param>
/// <returns>解析到的服务实例;若无法解析则返回 null。</returns>
public object? GetService(Type serviceType)
{
if (serviceType == typeof(IServiceProvider))
return this;
var existingInstance = container.Get(serviceType);
if (existingInstance != null)
return existingInstance;
var descriptor =
container.GetServicesUnsafe.LastOrDefault(candidate => candidate.ServiceType == serviceType);
if (descriptor != null)
return ResolveDescriptor(serviceType, descriptor);
if (!serviceType.IsAbstract && !serviceType.IsInterface)
return ActivatorUtilities.CreateInstance(this, serviceType);
logger.Trace($"Activation provider could not resolve {serviceType.Name}");
return null;
}
/// <summary>
/// 根据服务描述解析实例,并对单例描述进行缓存。
/// 这样可以保证同一类型在一次组件注册流程中只创建一次依赖实例。
/// </summary>
/// <param name="requestedType">请求的服务类型。</param>
/// <param name="descriptor">命中的服务描述。</param>
/// <returns>解析到的实例。</returns>
private object? ResolveDescriptor(Type requestedType, ServiceDescriptor descriptor)
{
if (descriptor.Lifetime == ServiceLifetime.Singleton &&
_singletonCache.TryGetValue(requestedType, out var cached))
return cached;
object? resolved = descriptor switch
{
{ ImplementationInstance: not null } => descriptor.ImplementationInstance,
{ ImplementationFactory: not null } => descriptor.ImplementationFactory(this),
{ ImplementationType: not null } => ActivatorUtilities.CreateInstance(this,
descriptor.ImplementationType),
_ => null
};
if (descriptor.Lifetime == ServiceLifetime.Singleton && resolved != null)
_singletonCache[requestedType] = resolved;
return resolved;
}
}
}

View File

@ -5,7 +5,6 @@ using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Extensions;
using Microsoft.Extensions.DependencyInjection;
namespace GFramework.Core.Architectures;
@ -20,6 +19,8 @@ internal sealed class ArchitectureComponentRegistry(
ArchitectureLifecycle lifecycle,
ILogger logger)
{
private readonly ArchitectureComponentActivator _activator = new(services.Container, logger);
#region Validation
/// <summary>
@ -63,7 +64,8 @@ internal sealed class ArchitectureComponentRegistry(
}
/// <summary>
/// 注册系统类型,由 DI 容器自动创建实例
/// 注册系统类型,并在注册阶段由当前服务集合立即创建实例。
/// 这样可以确保该系统参与当前架构初始化批次,而不是等到 Ready 之后首次解析时才延迟创建。
/// </summary>
/// <typeparam name="T">系统类型</typeparam>
/// <param name="onCreated">可选的实例创建后回调</param>
@ -72,21 +74,12 @@ internal sealed class ArchitectureComponentRegistry(
ValidateRegistration("system");
logger.Debug($"Registering system type: {typeof(T).Name}");
services.Container.RegisterFactory<T>(sp =>
{
// 1. DI 创建实例
var system = ActivatorUtilities.CreateInstance<T>(sp);
// 2. 框架默认处理
system.SetContext(architecture.Context);
lifecycle.RegisterLifecycleComponent(system);
// 3. 用户自定义处理(钩子)
onCreated?.Invoke(system);
logger.Debug($"System created: {typeof(T).Name}");
return system;
});
// 类型注册路径在注册阶段就物化实例,确保组件能参与当前初始化批次。
var system = _activator.CreateInstance<T>();
system.SetContext(architecture.Context);
lifecycle.RegisterLifecycleComponent(system);
onCreated?.Invoke(system);
services.Container.RegisterPlurality(system);
logger.Info($"System type registered: {typeof(T).Name}");
}
@ -118,7 +111,8 @@ internal sealed class ArchitectureComponentRegistry(
}
/// <summary>
/// 注册模型类型,由 DI 容器自动创建实例
/// 注册模型类型,并在注册阶段由当前服务集合立即创建实例。
/// 这样可以确保该模型参与当前架构初始化批次,而不是等到 Ready 之后首次解析时才延迟创建。
/// </summary>
/// <typeparam name="T">模型类型</typeparam>
/// <param name="onCreated">可选的实例创建后回调</param>
@ -127,18 +121,11 @@ internal sealed class ArchitectureComponentRegistry(
ValidateRegistration("model");
logger.Debug($"Registering model type: {typeof(T).Name}");
services.Container.RegisterFactory<T>(sp =>
{
var model = ActivatorUtilities.CreateInstance<T>(sp);
model.SetContext(architecture.Context);
lifecycle.RegisterLifecycleComponent(model);
// 用户自定义钩子
onCreated?.Invoke(model);
logger.Debug($"Model created: {typeof(T).Name}");
return model;
});
var model = _activator.CreateInstance<T>();
model.SetContext(architecture.Context);
lifecycle.RegisterLifecycleComponent(model);
onCreated?.Invoke(model);
services.Container.RegisterPlurality(model);
logger.Info($"Model type registered: {typeof(T).Name}");
}