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
}
}