修改 Startup 加载 和Module 加载

This commit is contained in:
chfei committed 2026-09-23 18:47:54 +08:00
1 parent c732ecb1d2
commit c7fb447034
17 files changed
+462 -383

No files matched your search

@@ -3,10 +3,13 @@ using MAX.Core.Interfaces;
using MAX.Framework.Commons;
using MAX.Framework.Dtos;
using MAX.Framework.Interfaces;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Win32;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
@@ -25,70 +28,37 @@ namespace MAX.Framework.DependencyInjection
];
/// <summary>
/// 兼容入口:只有服务集合,没有配置与环境(模块拿到的 <see cref="ModuleContext.Configuration"/> 是空配置),
/// 也拿不到 IConfigurationBuilder,所以模块自己的配置文件不会加载。新代码请用 <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>
/// 这个入口不加载模块自己的配置文件,需要模块配置请用 <c>builder.AddStoreHub()</c>。
/// </summary>
public static IServiceCollection AddStoreHub(this IServiceCollection services, IConfiguration? configuration, IHostEnvironment? environment)
public static IServiceCollection AddStore(this IHostApplicationBuilder host)
{
IEnumerable<Assembly> assemblies = GetApplicationAssemblies();
// 同一个类可能同时实现 IStartup 与 IModule,这里缓存实例,保证两个阶段拿到的是同一个对象
Dictionary<Type, object> instances = [];
ModuleRegistry modules = DiscoverModules(assemblies, instances);
return services.AddStoreHubCore(assemblies, modules, instances, configuration, environment);
return AddStoreCore(host, assemblies, instances);
}
/// <summary>
/// 注册应用服务的公共实现:宿主入口(<c>builder.AddStoreHub()</c>)与 <see cref="IServiceCollection"/> 入口共用。
/// </summary>
internal static IServiceCollection AddStoreHubCore(
this IServiceCollection services,
internal static IServiceCollection AddStoreCore(
IHostApplicationBuilder host,
IEnumerable<Assembly> assemblies,
ModuleRegistry modules,
IDictionary<Type, object> instances,
IConfiguration? configuration,
IHostEnvironment? environment)
IDictionary<Type, object> instances)
{
RegisterDependencyMarkers(services, assemblies);
RunStartups(services, assemblies, instances);
RegisterDependencyMarkers(host.Services, assemblies);
ModuleContext context = new(
services,
new ServiceRegistrarProxy(services),
configuration ?? new ConfigurationBuilder().Build(),
environment);
RunModules(host, assemblies, instances);
RunModules(modules, context);
// 注册表必须在 Build() 之前进容器,UseStoreHubModules() 才拿得到
services.AddSingleton(modules);
RunStartups(host.Services, assemblies, instances);
services.AddControllers(options =>
host.Services.AddControllers(options =>
{
options.Filters.Add<GlobalExceptionFilter>();
options.Filters.Add<UnifyResultFilter>();
@@ -113,7 +83,7 @@ namespace MAX.Framework.DependencyInjection
};
});
return services;
return host.Services;
}
/// <summary>
@@ -149,39 +119,33 @@ namespace MAX.Framework.DependencyInjection
}
}
}
private static IEnumerable<IStartup> Startups = [];
/// <summary>
/// 发现所有 <see cref="IStartup"/> 实现,按 <see cref="IStartup.Priority"/> 降序执行
/// </summary>
private static void RunStartups(IServiceCollection services, IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances)
{
IServiceRegistrar registrar = new ServiceRegistrarProxy(services);
foreach (IStartup startup in CreateInstances<IStartup>(assemblies, instances).OrderByDescending(s => s.Priority))
Startups = CreateInstances<IStartup>(assemblies, instances).OrderByDescending(s => s.Priority);
foreach (IStartup startup in Startups)
{
startup.Initialize();
startup.Register(registrar);
}
}
/// <summary>
/// 发现所有 <see cref="IModule"/> 实现,只创建实例,不执行任何阶段
/// </summary>
internal static ModuleRegistry DiscoverModules(IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances)
{
return new ModuleRegistry([.. CreateInstances<IModule>(assemblies, instances).OrderByDescending(m => m.Priority)]);
}
private static IEnumerable<IModule> Modules = [];
/// <summary>
/// 执行所有模块的服务注册阶段(<see cref="IModule.AddModule"/>)
/// </summary>
private static void RunModules(ModuleRegistry modules, ModuleContext context)
private static void RunModules(IHostApplicationBuilder host, IEnumerable<Assembly> assemblies, IDictionary<Type, object> instances)
{
foreach (IModule module in modules.Modules)
Modules = CreateInstances<IModule>(assemblies, instances).OrderByDescending(s => s.Priority);
foreach (IModule module in Modules)
{
try
{
module.AddModule(context);
module.AddModule(host);
}
catch (Exception ex)
{
@@ -234,7 +198,7 @@ namespace MAX.Framework.DependencyInjection
internal static IEnumerable<Assembly> GetApplicationAssemblies()
{
// 使用 AppTypeFinder:扫描应用输出目录 + 已加载程序集,
return StoreHubAppTypeFinder.Current.GetAssemblies();
return StoreAppTypeFinder.Current.GetAssemblies();
}
private static bool IsSystemInterface(Type type)
@@ -244,5 +208,20 @@ namespace MAX.Framework.DependencyInjection
|| type.Namespace.StartsWith("Microsoft", StringComparison.Ordinal);
}
public static IApplicationBuilder UseStore(this IApplicationBuilder app)
{
foreach (IStartup startup in Startups)
{
startup.Start((app as IHost).Services);
}
foreach (IModule module in Modules)
{
module.UseModule(app);
}
return app;
}
}
}