62 lines
2.0 KiB
C#
62 lines
2.0 KiB
C#
using MAX.Framework.Interfaces;
|
||
using Microsoft.AspNetCore.Builder;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
|
||
namespace MAX.Framework.DependencyInjection
|
||
{
|
||
/// <summary>
|
||
/// 宿主(Program.cs)入口:模块两阶段装配。
|
||
/// <code>
|
||
/// var builder = WebApplication.CreateBuilder(args);
|
||
/// builder.AddStoreHub(); // 阶段一:服务注册(自动执行所有 IModule.AddModule)
|
||
///
|
||
/// var app = builder.Build();
|
||
/// // ... 宿主自己的中间件、认证、端点 ...
|
||
/// app.UseStoreHubModules(); // 阶段二:管道装配(自动执行所有 IModule.UseModule)
|
||
/// app.Run();
|
||
/// </code>
|
||
/// </summary>
|
||
public static class HostBuilderExtensions
|
||
{
|
||
/// <summary>
|
||
/// 在 <see cref="WebApplicationBuilder"/> 上注册应用框架服务:
|
||
/// 等价于 <c>builder.Services.AddStoreHub(builder.Configuration, builder.Environment)</c>,
|
||
/// 区别是会把配置与环境一起包装成 <see cref="ModuleContext"/> 交给各模块。
|
||
/// </summary>
|
||
public static WebApplicationBuilder AddStoreHub(this WebApplicationBuilder builder)
|
||
{
|
||
builder.Services.AddStoreHub(builder.Configuration, builder.Environment);
|
||
return builder;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行所有模块的管道阶段(<see cref="IModule.UseModule"/>):注册中间件、看板、Map 端点等。
|
||
/// 必须在 <c>builder.Build()</c> 之后、<c>app.Run()</c> 之前调用;
|
||
/// 建议放在 <c>UseAuthorization()</c> 之后、<c>MapControllers()</c> 之前。
|
||
/// </summary>
|
||
public static WebApplication UseStoreHubModules(this WebApplication app)
|
||
{
|
||
// 宿主没调用过 AddStoreHub() 时容器里没有注册表,直接返回即可
|
||
ModuleRegistry? registry = app.Services.GetService<ModuleRegistry>();
|
||
if (registry is null)
|
||
{
|
||
return app;
|
||
}
|
||
|
||
foreach (IModule module in registry.Modules)
|
||
{
|
||
try
|
||
{
|
||
module.UseModule(app);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new InvalidOperationException($"模块 {module.GetType().FullName} 的 UseModule 执行失败。", ex);
|
||
}
|
||
}
|
||
|
||
return app;
|
||
}
|
||
}
|
||
}
|