using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using HT.Cloud.Code.Model; namespace HT.Cloud.Code { public static class GlobalContext { /// /// 构造函数 /// static GlobalContext() { // 未托管的对象 UnmanagedObjects = new ConcurrentBag(); } /// /// 服务集合 /// public static IServiceCollection Services { get; set; } /// /// 根服务 /// public static IServiceProvider RootServices { get; set; } public static IConfiguration Configuration { get; set; } public static IWebHostEnvironment HostingEnvironment { get; set; } /// /// 未托管的对象集合 /// public static readonly ConcurrentBag UnmanagedObjects; public static HttpContext HttpContext => RootServices?.GetService()?.HttpContext; public static SystemConfig SystemConfig { get; set; } /// /// 获取请求生存周期的服务(未注册返回null) /// /// /// /// public static TService GetService(IServiceProvider serviceProvider = null) where TService : class { return GetService(typeof(TService), serviceProvider) as TService; } /// /// 获取请求生存周期的服务(未注册返回null) /// /// /// /// public static object GetService(Type type, IServiceProvider serviceProvider = null) { return (serviceProvider ?? GetServiceProvider(type)).GetService(type); } /// /// 获取请求生存周期的服务(未注册异常) /// /// /// /// public static TService GetRequiredService(IServiceProvider serviceProvider = null) where TService : class { return GetRequiredService(typeof(TService), serviceProvider) as TService; } /// /// 获取请求生存周期的服务(未注册异常) /// /// /// /// public static object GetRequiredService(Type type, IServiceProvider serviceProvider = null) { return (serviceProvider ?? GetServiceProvider(type)).GetRequiredService(type); } /// /// 获取服务注册器 /// /// /// public static IServiceProvider GetServiceProvider(Type serviceType) { if (HostingEnvironment == null) { return RootServices; } if (RootServices != null && Services.Where((ServiceDescriptor u) => u.ServiceType == (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType)).Any((ServiceDescriptor u) => u.Lifetime == ServiceLifetime.Singleton)) { return RootServices; } // 第二选择是获取 HttpContext 对象的 RequestServices var httpContext = HttpContext; if (httpContext?.RequestServices != null) return httpContext.RequestServices; // 第三选择,创建新的作用域并返回服务提供器 else if (RootServices != null) { var scoped = RootServices.CreateScope(); UnmanagedObjects.Add(scoped); return scoped.ServiceProvider; } // 第四选择,构建新的服务对象(性能最差) else { var serviceProvider = Services.BuildServiceProvider(); UnmanagedObjects.Add(serviceProvider); return serviceProvider; } } /// /// GC 回收默认间隔 /// private const int GC_COLLECT_INTERVAL_SECONDS = 5; /// /// 记录最近 GC 回收时间 /// private static DateTime? LastGCCollectTime { get; set; } /// /// 释放所有未托管的对象 /// public static void DisposeUnmanagedObjects() { foreach (var dsp in UnmanagedObjects) { try { dsp?.Dispose(); } finally { } } // 强制手动回收 GC 内存 if (UnmanagedObjects.Any()) { var nowTime = DateTime.UtcNow; if ((LastGCCollectTime == null || (nowTime - LastGCCollectTime.Value).TotalSeconds > GC_COLLECT_INTERVAL_SECONDS)) { LastGCCollectTime = nowTime; GC.Collect(); GC.WaitForPendingFinalizers(); } } UnmanagedObjects.Clear(); } /// /// 获取版本号 /// /// public static string GetVersion() { Version version = Assembly.GetEntryAssembly().GetName().Version; return version.ToString(); } /// /// 获取请求跟踪 Id /// /// public static string GetTraceId() { return Activity.Current?.Id ?? (RootServices == null ? default : HttpContext?.TraceIdentifier); } /// /// 程序启动时,记录目录 /// /// public static void LogWhenStart(IWebHostEnvironment env) { StringBuilder sb = new StringBuilder(); sb.AppendLine("程序启动"); sb.AppendLine("ContentRootPath:" + env.ContentRootPath); sb.AppendLine("WebRootPath:" + env.WebRootPath); sb.AppendLine("IsDevelopment:" + env.IsDevelopment()); LogHelper.WriteWithTime(sb.ToString()); } /// /// 设置cache control /// /// public static void SetCacheControl(StaticFileResponseContext context) { int second = 365 * 24 * 60 * 60; context.Context.Response.Headers.Add("Cache-Control", new[] { "public,max-age=" + second }); context.Context.Response.Headers.Add("Expires", new[] { DateTime.UtcNow.AddYears(1).ToString("R") }); // Format RFC1123 } } }