模型注册

This commit is contained in:
chfei committed 2026-09-18 19:17:11 +08:00
1 parent 75d0e85218
commit 0e1620c1f9
11 files changed
+399 -41

No files matched your search

@@ -1,10 +1,12 @@
using MAX.Core.DependencyInjection;
using MAX.Core.DependencyInjection;
using MAX.Core.Interfaces;
using MAX.Framework.Commons;
using MAX.Framework.Dtos;
using MAX.Framework.Interfaces;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Diagnostics;
using System.Reflection;
@@ -23,18 +25,49 @@ namespace MAX.Framework.DependencyInjection
];
/// <summary>
/// 注册应用服务:
/// <list type="number">
/// <item>自动注册所有实现 <see cref="ISingletonDependency"/> / <see cref="IScopedDependency"/> / <see cref="ITransientDependency"/> 的类型;</item>
/// <item>发现所有 <see cref="IStartup"/>,按 <see cref="IStartup.Priority"/> 降序执行 Initialize + Register。</item>
/// </list>
/// 兼容入口:只有服务集合,没有配置与环境(模块拿到的 <see cref="ModuleContext.Configuration"/> 是空配置)。
/// 新代码请用 <c>builder.AddStoreHub()</c>。
/// </summary>
public static IServiceCollection AddStoreHub(this IServiceCollection services)
{
return services.AddStoreHub(null, null);
}
/// <summary>
/// 带配置的注册入口:<c>builder.Services.AddStoreHub(builder.Configuration)</c>
/// </summary>
public static IServiceCollection AddStoreHub(this IServiceCollection services, IConfiguration? configuration)
{
return services.AddStoreHub(configuration, null);
}
/// <summary>
/// 注册应用服务:
/// <list type="number">
/// <item>自动注册所有实现 <see cref="ISingletonDependency"/> / <see cref="IScopedDependency"/> / <see cref="ITransientDependency"/> 的类型;</item>
/// <item>发现所有 <see cref="IStartup"/>,按 <see cref="IStartup.Priority"/> 降序执行 Initialize + Register;</item>
/// <item>发现所有 <see cref="IModule"/>,按 <see cref="IModule.Priority"/> 降序执行 <see cref="IModule.AddModule"/>,
/// 并把模块实例登记进容器,留给 <c>app.UseStoreHubModules()</c> 执行管道阶段。</item>
/// </list>
/// </summary>
public static IServiceCollection AddStoreHub(this IServiceCollection services, IConfiguration? configuration, IHostEnvironment? environment)
{
IEnumerable<Assembly> assemblies = GetApplicationAssemblies();
// 同一个类可能同时实现 IStartup 与 IModule,这里缓存实例,保证两个阶段拿到的是同一个对象
Dictionary<Type, object> instances = [];
RegisterDependencyMarkers(services, assemblies);
RunStartups(services, assemblies);
RunModules(services, assemblies);
RunStartups(services, assemblies, instances);
ModuleContext context = new(
services,
new ServiceRegistrarProxy(services),
configuration ?? new ConfigurationBuilder().Build(),
environment);
// 注册表必须在 Build() 之前进容器,UseStoreHubModules() 才拿得到
services.AddSingleton(RunModules(assemblies, instances, context));
services.AddControllers(options =>
@@ -102,28 +135,55 @@ namespace MAX.Framework.DependencyInjection
/// <summary>
/// 发现所有 <see cref="IStartup"/> 实现,按 <see cref="IStartup.Priority"/> 降序执行
/// </summary>
private static void RunStartups(IServiceCollection services, IEnumerable<Assembly> assemblies)
private static void RunStartups(IServiceCollection services, IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances)
{
IServiceRegistrar registrar = new ServiceRegistrarProxy(services);
foreach (IStartup startup in GetConcreteTypes(assemblies)
.Where(t => typeof(IStartup).IsAssignableFrom(t))
.Select(t => (IStartup)Activator.CreateInstance(t, true)!)
.OrderByDescending(s => s.Priority))
foreach (IStartup startup in CreateInstances<IStartup>(assemblies, instances).OrderByDescending(s => s.Priority))
{
startup.Initialize();
startup.Register(registrar);
}
}
private static void RunModules(IServiceCollection services, IEnumerable<Assembly> assemblies)
{
IServiceRegistrar registrar = new ServiceRegistrarProxy(services);
foreach (IModule startup in GetConcreteTypes(assemblies)
.Where(t => typeof(IModule).IsAssignableFrom(t))
.Select(t => (IModule)Activator.CreateInstance(t, true)!))
/// <summary>
/// 发现所有 <see cref="IModule"/> 实现,按 <see cref="IModule.Priority"/> 降序执行服务注册阶段
/// </summary>
private static ModuleRegistry RunModules(IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances, ModuleContext context)
{
List<IModule> modules = [.. CreateInstances<IModule>(assemblies, instances).OrderByDescending(m => m.Priority)];
foreach (IModule module in modules)
{
startup.AddModule(services);
try
{
module.AddModule(context);
}
catch (Exception ex)
{
// 带上模块名,避免只看到一个没有上下文的异常
throw new InvalidOperationException($"模块 {module.GetType().FullName} 的 AddModule 执行失败。", ex);
}
}
return new ModuleRegistry(modules);
}
/// <summary>
/// 反射创建(或复用)所有实现 <typeparamref name="T"/> 的具体类型实例
/// </summary>
private static IEnumerable<T> CreateInstances<T>(IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances) where T : class
{
foreach (Type type in GetConcreteTypes(assemblies).Where(t => typeof(T).IsAssignableFrom(t)))
{
if (!instances.TryGetValue(type, out object? instance))
{
instance = Activator.CreateInstance(type, true)
?? throw new InvalidOperationException($"无法创建 {type.FullName} 的实例(需要有参数量为 0 的构造函数)。");
instances[type] = instance;
}
yield return (T)instance;
}
}