using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using WIDESEA_Core.Core; using WIDESEA_Core.Helper; using WIDESEA_Core.HttpContextUser; namespace WIDESEA_Core { /// /// 应用程序全局静态类,提供应用运行状态、服务获取、配置管理等核心功能 /// /// /// 包含功能: /// 1. 应用运行状态管理(IsRun/IsBuild) /// 2. 程序集和类型加载(Assemblies/EffectiveTypes) /// 3. 服务容器访问(RootServices/GetService) /// 4. 环境配置访问(WebHostEnvironment/Configuration) /// 5. 选项模式支持(GetOptions/GetConfig) /// 6. HTTP上下文访问(HttpContext/User) /// public class App { static App() { EffectiveTypes = Assemblies.SelectMany(GetTypes); } /// /// 表示应用程序是否正在运行的标志 /// private static bool _isRun; /// /// 获取或设置一个值,指示当前是否为构建状态 /// public static bool IsBuild { get; set; } /// /// 获取或设置应用程序是否正在运行的标志 /// /// /// 设置此属性时也会同时更新IsBuild属性 /// public static bool IsRun { get => _isRun; set => _isRun = IsBuild = value; } /// /// 有效期 /// public static DateTime? ExpDateTime = null; /// /// 获取当前应用程序域中所有程序集的静态集合 /// /// /// 该集合在应用程序启动时初始化,包含通过RuntimeExtension.GetAllAssemblies()方法加载的所有程序集 /// public static readonly IEnumerable Assemblies = RuntimeExtension.GetAllAssemblies(); /// /// 有效的类型集合,包含所有需要处理的类型 /// public static readonly IEnumerable EffectiveTypes; /// /// 获取根服务提供程序。当应用程序正在运行或构建时返回服务提供程序,否则返回null。 /// public static IServiceProvider? RootServices => IsRun || IsBuild ? InternalApp.RootServices : null; /// /// 获取当前Web主机环境信息 /// public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment; /// /// 获取当前应用程序的主机环境信息 /// public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment; /// /// 获取应用程序的配置信息 /// /// 全局配置接口 public static IConfiguration Configuration => InternalApp.Configuration; /// /// 获取请求上下文 /// public static HttpContext? HttpContext => RootServices?.GetService()?.HttpContext; /// /// 获取当前用户服务实例 /// /// 当前用户接口实例,可能为null public static IUser? User => GetService(); #region Service /// /// 获取指定类型的服务提供者 /// /// 要获取的服务类型 /// 是否必须构建服务提供者 /// 当服务不可用时是否抛出异常 /// 服务提供者实例,若不可用则返回null /// /// 该方法会按以下顺序尝试获取服务提供者: /// 1. 如果是单例服务且已注册,返回根服务提供者 /// 2. 尝试从当前HttpContext获取请求作用域的服务提供者 /// 3. 创建新的作用域并返回其服务提供者 /// 4. 如果mustBuild为true,构建并返回新的服务提供者 /// public static IServiceProvider? GetServiceProvider(Type serviceType, bool mustBuild = false, bool throwException = true) { if (HostEnvironment == null || RootServices != null && InternalApp.InternalServices .Where((u => u.ServiceType == (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType))) .Any((u => u.Lifetime == ServiceLifetime.Singleton))) return RootServices; //获取请求生存周期的服务 if (HttpContext?.RequestServices != null) return HttpContext.RequestServices; if (RootServices != null) { IServiceScope scope = RootServices.CreateScope(); return scope.ServiceProvider; } if (mustBuild) { if (throwException) { throw new ApplicationException("当前不可用,必须要等到 WebApplication Build后"); } return default; } ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider(); return serviceProvider; } /// /// 获取指定类型的服务实例 /// /// 要获取的服务类型 /// 是否必须构建服务实例,默认为true /// 返回请求的服务实例,若未找到则返回null public static TService? GetService(bool mustBuild = true) where TService : class { TService? test = GetService(typeof(TService), null, mustBuild) as TService; return test; } /// /// 获取指定类型的服务实例 /// /// 服务类型 /// 可选的服务提供者,如果为null则使用默认提供者 /// 是否必须构建服务,默认为true /// 服务实例,如果获取失败则返回null public static TService? GetService(IServiceProvider? serviceProvider, bool mustBuild = true) where TService : class => (serviceProvider ?? GetServiceProvider(typeof(TService), mustBuild, false))?.GetService(); /// /// 获取指定类型的服务实例 /// /// 要获取的服务类型 /// 可选的服务提供者,若为空则使用默认提供者 /// 是否必须构建服务,默认为true /// 服务实例,若未找到则返回null public static object? GetService(Type type, IServiceProvider? serviceProvider = null, bool mustBuild = true) { object? obj = (serviceProvider ?? GetServiceProvider(type, mustBuild, false))?.GetService(type); return obj; } #endregion #region private /// /// 从指定程序集中获取所有公共类型 /// /// 要扫描的程序集 /// 程序集中所有公共类型的枚举 /// /// 如果获取类型时发生错误,将静默处理并返回空集合 /// private static IEnumerable GetTypes(Assembly ass) { Type[] source = Array.Empty(); try { source = ass.GetTypes(); } catch { //$@"Error load `{ass.FullName}` assembly.".WriteErrorLine(); } return source.Where(u => u.IsPublic); } #endregion #region Options /// /// 获取指定类型的配置选项实例 /// /// 配置选项类型,必须实现IConfigurableOptions接口 /// 配置节中对应的选项实例 public static TOptions GetConfig() where TOptions : class, IConfigurableOptions { TOptions instance = Configuration .GetSection(ConfigurableOptions.GetConfigurationPath(typeof(TOptions))) .Get(); return instance; } /// /// 从服务提供器中获取指定类型的选项配置 /// /// 选项类型,必须为类且有无参构造函数 /// 根服务提供器 /// 可选的服务提供器,若未指定则使用根服务提供器 /// 获取到的选项实例,若未找到则返回null public static TOptions? GetOptions(IServiceProvider? rootServices, IServiceProvider serviceProvider = null) where TOptions : class, new() { IOptions? service = GetService>(serviceProvider ?? rootServices, false); return service?.Value; } /// /// 从服务提供器中获取指定类型TOptions的选项监控实例的当前值 /// /// 选项类型,必须为可实例化的类 /// 可选的服务提供器,若未指定则使用根服务 /// TOptions类型的当前选项值,若服务未注册则返回null public static TOptions? GetOptionsMonitor(IServiceProvider serviceProvider = null) where TOptions : class, new() { IOptionsMonitor? service = GetService>(serviceProvider ?? RootServices, false); return service?.CurrentValue; } /// /// 获取指定选项类型的快照实例 /// /// 选项类型,必须有无参构造函数 /// 可选的服务提供者,默认为null /// 选项实例的快照,如果服务未注册则返回null public static TOptions? GetOptionsSnapshot(IServiceProvider serviceProvider = null) where TOptions : class, new() { IOptionsSnapshot? service = GetService>(serviceProvider, false); return service?.Value; } #endregion } }