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; namespace MAX.Framework.DependencyInjection { /// /// IOC 注册入口(由宿主 Program.cs 调用) /// public static class ServiceCollectionExtensions { private static readonly Type[] DependencyMarkers = [ typeof(ISingletonDependency), typeof(IScopedDependency), typeof(ITransientDependency), ]; /// /// 兼容入口:只有服务集合,没有配置与环境(模块拿到的 是空配置), /// 也拿不到 IConfigurationBuilder,所以模块自己的配置文件不会加载。新代码请用 builder.AddStoreHub()。 /// public static IServiceCollection AddStoreHub(this IServiceCollection services) { return services.AddStoreHub(null, null); } /// /// 带配置的注册入口:builder.Services.AddStoreHub(builder.Configuration) /// public static IServiceCollection AddStoreHub(this IServiceCollection services, IConfiguration? configuration) { return services.AddStoreHub(configuration, null); } /// /// 注册应用服务: /// /// 自动注册所有实现 / / 的类型; /// 发现所有 ,按 降序执行 Initialize + Register; /// 发现所有 ,按 降序执行 , /// 并把模块实例登记进容器,留给 app.UseStoreHubModules() 执行管道阶段。 /// /// 这个入口不加载模块自己的配置文件,需要模块配置请用 builder.AddStoreHub()。 /// public static IServiceCollection AddStoreHub(this IServiceCollection services, IConfiguration? configuration, IHostEnvironment? environment) { IEnumerable assemblies = GetApplicationAssemblies(); // 同一个类可能同时实现 IStartup 与 IModule,这里缓存实例,保证两个阶段拿到的是同一个对象 Dictionary instances = []; ModuleRegistry modules = DiscoverModules(assemblies, instances); return services.AddStoreHubCore(assemblies, modules, instances, configuration, environment); } /// /// 注册应用服务的公共实现:宿主入口(builder.AddStoreHub())与 入口共用。 /// internal static IServiceCollection AddStoreHubCore( this IServiceCollection services, IEnumerable assemblies, ModuleRegistry modules, IDictionary instances, IConfiguration? configuration, IHostEnvironment? environment) { RegisterDependencyMarkers(services, assemblies); RunStartups(services, assemblies, instances); ModuleContext context = new( services, new ServiceRegistrarProxy(services), configuration ?? new ConfigurationBuilder().Build(), environment); RunModules(modules, context); // 注册表必须在 Build() 之前进容器,UseStoreHubModules() 才拿得到 services.AddSingleton(modules); services.AddControllers(options => { options.Filters.Add(); options.Filters.Add(); }).ConfigureApiBehaviorOptions(options => { options.InvalidModelStateResponseFactory = context => { // 取出所有校验错误信息,拼成一个字符串(或者只取第一个) var errors = context.ModelState .Where(e => e.Value?.Errors.Count > 0) .SelectMany(e => e.Value!.Errors.Select(err => err.ErrorMessage)) .ToList(); var msg = string.Join("; ", errors); var result = ApiResult.Fail(msg, ResultCode.ValidationError); return new ObjectResult(result) { StatusCode = 200 // 和其他接口保持一致,用Code表达失败,而不是HTTP 400 }; }; }); return services; } /// /// 自动注册标记接口(ISingletonDependency / IScopedDependency / ITransientDependency)的实现类型 /// private static void RegisterDependencyMarkers(IServiceCollection services, IEnumerable assemblies) { foreach (Type type in GetConcreteTypes(assemblies)) { Debug.WriteLine(type.Namespace); Type? marker = DependencyMarkers.FirstOrDefault(m => m.IsAssignableFrom(type)); if (marker is null) { continue; } ServiceLifetime lifetime = marker == typeof(ISingletonDependency) ? ServiceLifetime.Singleton : marker == typeof(IScopedDependency) ? ServiceLifetime.Scoped : ServiceLifetime.Transient; // 注册为自身 services.Add(new ServiceDescriptor(type, type, lifetime)); // 注册为实现的接口(排除标记接口与系统接口) foreach (Type iface in type.GetInterfaces()) { if (DependencyMarkers.Contains(iface) || IsSystemInterface(iface)) { continue; } services.Add(new ServiceDescriptor(iface, type, lifetime)); } } } /// /// 发现所有 实现,按 降序执行 /// private static void RunStartups(IServiceCollection services, IEnumerable assemblies, IDictionary instances) { IServiceRegistrar registrar = new ServiceRegistrarProxy(services); foreach (IStartup startup in CreateInstances(assemblies, instances).OrderByDescending(s => s.Priority)) { startup.Initialize(); startup.Register(registrar); } } /// /// 发现所有 实现,只创建实例,不执行任何阶段 /// internal static ModuleRegistry DiscoverModules(IEnumerable assemblies, IDictionary instances) { return new ModuleRegistry([.. CreateInstances(assemblies, instances).OrderByDescending(m => m.Priority)]); } /// /// 执行所有模块的服务注册阶段() /// private static void RunModules(ModuleRegistry modules, ModuleContext context) { foreach (IModule module in modules.Modules) { try { module.AddModule(context); } catch (Exception ex) { // 带上模块名,避免只看到一个没有上下文的异常 throw new InvalidOperationException($"模块 {module.GetType().FullName} 的 AddModule 执行失败。", ex); } } } /// /// 反射创建(或复用)所有实现 的具体类型实例 /// private static IEnumerable CreateInstances(IEnumerable assemblies, IDictionary 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; } } private static IEnumerable GetConcreteTypes(IEnumerable assemblies) { return assemblies .SelectMany(SafeGetTypes) .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericTypeDefinition); } private static IEnumerable SafeGetTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.OfType(); } } /// /// 应用程序集(模块、Startup 都从这里发现) /// internal static IEnumerable GetApplicationAssemblies() { // 使用 AppTypeFinder:扫描应用输出目录 + 已加载程序集, return StoreHubAppTypeFinder.Current.GetAssemblies(); } private static bool IsSystemInterface(Type type) { return type.Namespace is null || type.Namespace.StartsWith("System", StringComparison.Ordinal) || type.Namespace.StartsWith("Microsoft", StringComparison.Ordinal); } } }