//using MAX.Framework.Interfaces; //using Microsoft.AspNetCore.Builder; //using Microsoft.Extensions.Configuration; //using Microsoft.Extensions.Configuration.Json; //using Microsoft.Extensions.DependencyInjection; //using System.Reflection; //namespace MAX.Framework.DependencyInjection //{ // /// // /// 宿主(Program.cs)入口:模块两阶段装配 + 模块自己的配置文件。 // /// // /// var builder = WebApplication.CreateBuilder(args); // /// builder.AddStoreHub(); // 阶段一:加载各模块配置文件 + 自动执行所有 IModule.AddModule // /// // /// var app = builder.Build(); // /// // ... 宿主自己的中间件、认证、端点 ... // /// app.UseStoreHubModules(); // 阶段二:管道装配(自动执行所有 IModule.UseModule) // /// app.Run(); // /// // /// // public static class HostBuilderExtensions // { // /// // /// 在 上注册应用框架服务: // /// // /// 发现所有 ; // /// 把每个模块声明的 并入宿主配置树(宿主 appsettings.json 不需要放模块的配置); // /// 再执行 builder.Services.AddStoreHub(builder.Configuration, builder.Environment)。 // /// // /// // public static WebApplicationBuilder AddStore(this WebApplicationBuilder builder) // { // IEnumerable assemblies = ServiceCollectionExtensions.GetApplicationAssemblies(); // // 同一个类可能同时实现 IStartup 与 IModule,这里缓存实例,保证后面两个阶段拿到的是同一个对象 // Dictionary instances = []; // ModuleRegistry modules = ServiceCollectionExtensions.DiscoverModules(assemblies, instances); // // 必须在跑 AddModule 之前并入,模块注册时才读得到自己的配置节 // foreach (IModule module in modules.Modules) // { // AddModuleConfigurationFile(builder.Configuration, module); // } // builder.Services.AddStoreHubCore(assemblies, modules, instances, builder.Configuration, builder.Environment); // return builder; // } // /// // /// 执行所有模块的管道阶段():注册中间件、看板、Map 端点等。 // /// // public static WebApplication UseStoreHubModules(this WebApplication app) // { // // 宿主没调用过 AddStoreHub() 时容器里没有注册表,直接返回即可 // ModuleRegistry? registry = app.Services.GetService(); // 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; // } // /// // /// 把模块自己的配置文件并进宿主配置:插在 appsettings*.json 之后、环境变量/命令行之前, // /// 这样模块配置能覆盖宿主 appsettings.json,同时仍然允许用环境变量/命令行覆盖它。 // /// // private static void AddModuleConfigurationFile(IConfigurationBuilder configuration, IModule module) // { // string? fileName = module.ConfigurationFile; // if (string.IsNullOrWhiteSpace(fileName)) // { // return; // } // string path = Path.IsPathRooted(fileName) // ? fileName // : Path.Combine(AppContext.BaseDirectory, fileName); // JsonConfigurationSource source = new() // { // Path = path, // Optional = true, // 文件不存在时不报错(模块没配就是没有) // ReloadOnChange = true // 允许改配置不重启(与 appsettings.json 行为一致) // }; // source.ResolveFileProvider(); // IList sources = configuration.Sources; // int index = sources.Count; // // 找到最后一个 appsettings*.json,插到它后面 // for (int i = sources.Count - 1; i >= 0; i--) // { // if (sources[i] is FileConfigurationSource file // && Path.GetFileName(file.Path).StartsWith("appsettings", StringComparison.OrdinalIgnoreCase)) // { // index = i + 1; // break; // } // } // sources.Insert(index, source); // if (configuration is IConfigurationRoot root) // { // root.Reload(); // } // } // } //}