mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
refactor(arch): 重构架构组件注册机制
- 将组件注册逻辑提取到独立的 ArchitectureComponentRegistry 类中 - 实现 ArchitectureComponentActivator 来支持注册阶段实例化组件 - 更新系统和模型注册文档说明,明确在注册阶段创建实例并参与初始化 - 修复类型注册在架构准备就绪后的行为一致性问题 - 添加完整的组件注册行为测试覆盖实例注册、工厂注册和生命周期管理 - 优化依赖注入解析机制,支持构造函数依赖和单例缓存
This commit is contained in:
parent
01dc1523a5
commit
bb2b3a0c60
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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}");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user