找回密码
 立即注册
首页 业界区 安全 GlobalService类

GlobalService类

袁勤 2025-6-28 23:59:57
  1. public class GlobalService
  2. {
  3.     private static IServiceScope? _currentScope;
  4.     private static readonly Lazy<string> _serverAddress = new Lazy<string>(GetServerAddress, true);
  5.     private static readonly Lazy<string> _serverPort = new Lazy<string>(GetServerPort, true);
  6.     private static DateTime? _serviceStartTime;
  7.     // 核心服务
  8.     public static ILogger? Logger { get; private set; }
  9.     public static IWebHostEnvironment? WebHostEnvironment { get; private set; }
  10.     public static IServiceProvider? ServiceProvider { get; private set; }
  11.     public static IConfiguration? Configuration { get; private set; }
  12.     public static IHttpContextAccessor? HttpContextAccessor { get; private set; }
  13.     public static IHostApplicationLifetime? ApplicationLifetime { get; private set; }
  14.     // 使用Lazy<T>实现线程安全的延迟初始化
  15.     private static readonly Lazy<IServiceScope> _lazyScope = new Lazy<IServiceScope>(
  16.         () => ServiceProvider!.CreateScope(),
  17.         LazyThreadSafetyMode.ExecutionAndPublication
  18.     );
  19.     #region 便捷访问属性 - 环境与应用信息
  20.     /// <summary>当前应用程序名称</summary>
  21.     public static string ApplicationName => WebHostEnvironment?.ApplicationName ?? "UnknownApp";
  22.     /// <summary>当前环境名称(Development/Production等)</summary>
  23.     public static string EnvironmentName => WebHostEnvironment?.EnvironmentName ?? "Unknown";
  24.     /// <summary>应用程序根路径</summary>
  25.     public static string ContentRootPath => WebHostEnvironment?.ContentRootPath ?? "";
  26.     /// <summary>Web静态文件根路径</summary>
  27.     public static string WebRootPath => WebHostEnvironment?.WebRootPath ?? "";
  28.     /// <summary>服务启动时间</summary>
  29.     public static DateTime ServiceStartTime => _serviceStartTime ??= DateTime.Now;
  30.     /// <summary>服务已运行时间</summary>
  31.     public static TimeSpan ServiceUptime => DateTime.Now - ServiceStartTime;
  32.     /// <summary>检查应用是否处于开发环境</summary>
  33.     public static bool IsDevelopment => WebHostEnvironment?.IsDevelopment() ?? false;
  34.     /// <summary>检查应用是否处于生产环境</summary>
  35.     public static bool IsProduction => WebHostEnvironment?.IsProduction() ?? false;
  36.     #endregion
  37.     #region 便捷访问属性 - 系统信息
  38.     /// <summary>获取操作系统信息</summary>
  39.     public static string OSInformation => Environment.OSVersion.ToString();
  40.     /// <summary>获取.NET运行时版本</summary>
  41.     public static string RuntimeVersion => Environment.Version.ToString();
  42.     /// <summary>获取应用进程ID</summary>
  43.     public static int ProcessId => Process.GetCurrentProcess().Id;
  44.     #endregion
  45.     #region 便捷访问属性 - 客户端信息
  46.     /// <summary>获取当前请求的客户端IPv4地址(支持代理服务器场景)</summary>
  47.     public static string ClientIPv4Address
  48.     {
  49.         get
  50.         {
  51.             try
  52.             {
  53.                 var context = HttpContextAccessor?.HttpContext;
  54.                 if (context == null) return "Unknown";
  55.                 // 优先从请求头获取代理IP(如Nginx/X-Forwarded-For)
  56.                 var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
  57.                 if (string.IsNullOrEmpty(ip))
  58.                 {
  59.                     ip = context.Connection.RemoteIpAddress?.ToString();
  60.                 }
  61.                 // 提取IPv4地址(处理可能的端口或IPv6格式)
  62.                 if (ip != null)
  63.                 {
  64.                     var parts = ip.Split(',', ':', ']').FirstOrDefault(p => !string.IsNullOrEmpty(p.Trim()));
  65.                     if (IPAddress.TryParse(parts, out var address) && address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
  66.                     {
  67.                         return address.ToString();
  68.                     }
  69.                 }
  70.                 return "Unknown";
  71.             }
  72.             catch
  73.             {
  74.                 return "Unknown";
  75.             }
  76.         }
  77.     }
  78.     /// <summary>获取当前请求的客户端端口号</summary>
  79.     public static int? ClientPort
  80.     {
  81.         get
  82.         {
  83.             try
  84.             {
  85.                 return HttpContextAccessor?.HttpContext?.Connection?.RemotePort;
  86.             }
  87.             catch
  88.             {
  89.                 return null;
  90.             }
  91.         }
  92.     }
  93.     /// <summary>获取当前请求的完整URL</summary>
  94.     public static string? CurrentRequestUrl
  95.     {
  96.         get
  97.         {
  98.             try
  99.             {
  100.                 var context = HttpContextAccessor?.HttpContext;
  101.                 if (context == null) return null;
  102.                 return $"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}{context.Request.QueryString}";
  103.             }
  104.             catch
  105.             {
  106.                 return null;
  107.             }
  108.         }
  109.     }
  110.     /// <summary>获取当前认证用户的ID(如果有)</summary>
  111.     public static string? CurrentUserId
  112.     {
  113.         get
  114.         {
  115.             try
  116.             {
  117.                 var context = HttpContextAccessor?.HttpContext;
  118.                 return context?.User?.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
  119.             }
  120.             catch
  121.             {
  122.                 return null;
  123.             }
  124.         }
  125.     }
  126.     /// <summary>获取当前认证用户的名称(如果有)</summary>
  127.     public static string? CurrentUserName
  128.     {
  129.         get
  130.         {
  131.             try
  132.             {
  133.                 var context = HttpContextAccessor?.HttpContext;
  134.                 return context?.User?.Identity?.Name;
  135.             }
  136.             catch
  137.             {
  138.                 return null;
  139.             }
  140.         }
  141.     }
  142.     #endregion
  143.     #region 便捷访问属性 - 服务地址信息
  144.     /// <summary>获取当前服务侦听的IPv4地址</summary>
  145.     public static string ServerAddress => _serverAddress.Value;
  146.     /// <summary>获取当前服务侦听的端口号</summary>
  147.     public static string ServerPort => _serverPort.Value;
  148.     /// <summary>获取服务正在监听的完整地址(包含协议和端口)</summary>
  149.     public static string ServiceListeningAddress
  150.     {
  151.         get
  152.         {
  153.             try
  154.             {
  155.                 if (ServiceProvider == null) return "Unknown";
  156.                 var server = ServiceProvider.GetRequiredService<IServer>();
  157.                 var addressesFeature = server.Features.Get<IServerAddressesFeature>();
  158.                 if (addressesFeature?.Addresses == null || !addressesFeature.Addresses.Any())
  159.                 {
  160.                     return "Unknown";
  161.                 }
  162.                 return addressesFeature.Addresses.First();
  163.             }
  164.             catch
  165.             {
  166.                 return "Unknown";
  167.             }
  168.         }
  169.     }
  170.     /// <summary>获取当前服务实例的IPv4地址(不包含端口)</summary>
  171.     public static string ServiceIPv4Address
  172.     {
  173.         get
  174.         {
  175.             try
  176.             {
  177.                 var host = Dns.GetHostEntry(Dns.GetHostName());
  178.                 foreach (var ip in host.AddressList)
  179.                 {
  180.                     if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
  181.                     {
  182.                         return ip.ToString();
  183.                     }
  184.                 }
  185.                 return "127.0.0.1";
  186.             }
  187.             catch
  188.             {
  189.                 return "127.0.0.1";
  190.             }
  191.         }
  192.     }
  193.     /// <summary>获取当前服务实例的端口号</summary>
  194.     public static int ServicePort
  195.     {
  196.         get
  197.         {
  198.             try
  199.             {
  200.                 var address = ServiceListeningAddress;
  201.                 if (string.IsNullOrEmpty(address)) return 0;
  202.                 if (Uri.TryCreate(address, UriKind.Absolute, out var uri))
  203.                 {
  204.                     return uri.Port;
  205.                 }
  206.                 else if (address.Contains(":"))
  207.                 {
  208.                     var parts = address.Split(':').LastOrDefault();
  209.                     if (int.TryParse(parts, out var port))
  210.                     {
  211.                         return port;
  212.                     }
  213.                 }
  214.                 return 0;
  215.             }
  216.             catch
  217.             {
  218.                 return 0;
  219.             }
  220.         }
  221.     }
  222.     #endregion
  223.     #region 便捷访问属性 - 请求信息
  224.     /// <summary>获取当前请求路径</summary>
  225.     public static string? RequestPath => HttpContextAccessor?.HttpContext?.Request?.Path;
  226.     /// <summary>获取当前请求方法(GET/POST等)</summary>
  227.     public static string? RequestMethod => HttpContextAccessor?.HttpContext?.Request?.Method;
  228.     #endregion
  229.     /// <summary>创建临时服务作用域(使用后需手动释放)</summary>
  230.     public static IServiceScope CreateScope() => ServiceProvider!.CreateScope();
  231.     /// <summary>获取当前活动的作用域(单例模式)</summary>
  232.     public static IServiceScope CurrentScope => _lazyScope.Value;
  233.     /// <summary>初始化全局服务(在应用启动时调用)</summary>
  234.     public static void Initialize(IServiceProvider serviceProvider)
  235.     {
  236.         ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
  237.         // 从服务容器中获取核心服务
  238.         WebHostEnvironment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
  239.         Configuration = serviceProvider.GetRequiredService<IConfiguration>();
  240.         HttpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
  241.         ApplicationLifetime = serviceProvider.GetRequiredService<IHostApplicationLifetime>();
  242.         // 创建全局日志记录器
  243.         Logger = serviceProvider.GetRequiredService<ILoggerFactory>()
  244.                                .CreateLogger("GlobalService");
  245.     }
  246.     /// <summary>释放全局资源</summary>
  247.     public static void Dispose()
  248.     {
  249.         if (_lazyScope.IsValueCreated)
  250.         {
  251.             _lazyScope.Value.Dispose();
  252.         }
  253.         _currentScope = null;
  254.     }
  255.     /// <summary>从当前作用域获取服务</summary>
  256.     public static T GetService<T>() where T : notnull
  257.         => CurrentScope.ServiceProvider.GetRequiredService<T>();
  258.     /// <summary>从临时作用域获取服务(使用后需释放作用域)</summary>
  259.     public static T GetScopedService<T>() where T : notnull
  260.         => CreateScope().ServiceProvider.GetRequiredService<T>();
  261.     /// <summary>从配置中获取强类型配置对象</summary>
  262.     public static T GetConfig<T>(string sectionName) where T : new()
  263.     {
  264.         var config = new T();
  265.         Configuration?.GetSection(sectionName).Bind(config);
  266.         return config;
  267.     }
  268.     /// <summary>从配置中获取值</summary>
  269.     public static string? GetConfigValue(string key) => Configuration?[key];
  270.     /// <summary>优雅地停止应用程序</summary>
  271.     public static void StopApplication() => ApplicationLifetime?.StopApplication();
  272.     // Fix for CS1061: Replace the incorrect usage of `ServerFeatures` with the correct way to access `IServerAddressesFeature` from the service provider.
  273.     private static string GetServerAddress()
  274.     {
  275.         try
  276.         {
  277.             if (ServiceProvider == null) return "Unknown";
  278.             var server = ServiceProvider.GetRequiredService<IServer>();
  279.             var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses;
  280.             return addresses?
  281.                 .Select(a => new Uri(a))
  282.                 .FirstOrDefault(uri =>
  283.                     uri.Host == "localhost" ||
  284.                     uri.Host == "127.0.0.1" ||
  285.                     uri.Host.Contains('.')
  286.                 )?.Host ?? "Unknown";
  287.         }
  288.         catch
  289.         {
  290.             return "Unknown";
  291.         }
  292.     }
  293.     private static string GetServerPort()
  294.     {
  295.         try
  296.         {
  297.             if (ServiceProvider == null) return "Unknown";
  298.             var server = ServiceProvider.GetRequiredService<IServer>();
  299.             var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses;
  300.             return addresses?
  301.                 .Select(a => new Uri(a))
  302.                 .FirstOrDefault()?
  303.                 .Port.ToString() ?? "Unknown";
  304.         }
  305.         catch
  306.         {
  307.             return "Unknown";
  308.         }
  309.     }
  310.     #region 便捷访问属性 - 内存使用
  311.     /// <summary>获取当前应用的内存使用情况</summary>
  312.     public static MemoryInfo GetMemoryInfo()
  313.     {
  314.         try
  315.         {
  316.             var process = Process.GetCurrentProcess();
  317.             return new MemoryInfo
  318.             {
  319.                 WorkingSet = process.WorkingSet64 / (1024 * 1024), // MB
  320.                 PrivateMemorySize = process.PrivateMemorySize64 / (1024 * 1024), // MB
  321.                 VirtualMemorySize = process.VirtualMemorySize64 / (1024 * 1024), // MB
  322.                 PeakWorkingSet = process.PeakWorkingSet64 / (1024 * 1024), // MB
  323.                 PeakPrivateMemorySize = process.PrivateMemorySize64 / (1024 * 1024),
  324.                 PeakVirtualMemorySize = process.PeakVirtualMemorySize64 / (1024 * 1024) // MB
  325.             };
  326.         }
  327.         catch (Exception ex)
  328.         {
  329.             LogException(ex, nameof(GetMemoryInfo));
  330.             return new MemoryInfo();
  331.         }
  332.     }
  333.     // 在GlobalService类中添加以下方法
  334.     private static void LogException(Exception ex, string methodName)
  335.     {
  336.         Logger?.LogError(ex, $"GlobalService方法[{methodName}]发生异常: {ex.Message}");
  337.     }
  338.     /// <summary>内存使用信息类</summary>
  339.     public class MemoryInfo
  340.     {
  341.         public long WorkingSet { get; set; }       // 工作集(MB)
  342.         public long PrivateMemorySize { get; set; } // 私有内存(MB)
  343.         public long VirtualMemorySize { get; set; } // 虚拟内存(MB)
  344.         public long PeakWorkingSet { get; set; }    // 峰值工作集(MB)
  345.         public long PeakPrivateMemorySize { get; set; } // 峰值私有内存(MB)
  346.         public long PeakVirtualMemorySize { get; set; } // 峰值虚拟内存(MB)
  347.     }
  348.     #endregion
  349.     /// <summary>
  350.     /// 获取GlobalService中所有可展示的信息
  351.     /// </summary>
  352.     /// <param name="useChinese">是否使用中文显示,默认使用英文</param>
  353.     /// <returns>包含所有信息的字典,键为显示名称,值为对应值</returns>
  354.     public static Dictionary<string, object> GetAllDisplayInfo(bool useChinese = false)
  355.     {
  356.         // 中英文显示名称映射
  357.         var displayNames = new Dictionary<string, string>
  358.     {
  359.         // 环境与应用信息
  360.         { "ApplicationName", useChinese ? "应用程序名称" : "Application Name" },
  361.         { "EnvironmentName", useChinese ? "环境名称" : "Environment Name" },
  362.         { "ContentRootPath", useChinese ? "应用程序根路径" : "Content Root Path" },
  363.         { "WebRootPath", useChinese ? "Web静态文件根路径" : "Web Root Path" },
  364.         { "ServiceStartTime", useChinese ? "服务启动时间" : "Service Start Time" },
  365.         { "ServiceUptime", useChinese ? "服务已运行时间" : "Service Uptime" },
  366.         { "IsDevelopment", useChinese ? "是否开发环境" : "Is Development" },
  367.         { "IsProduction", useChinese ? "是否生产环境" : "Is Production" },
  368.         
  369.         // 客户端信息
  370.         { "ClientIPv4Address", useChinese ? "客户端IPv4地址" : "Client IPv4 Address" },
  371.         { "ClientPort", useChinese ? "客户端端口号" : "Client Port" },
  372.         { "CurrentRequestUrl", useChinese ? "当前请求URL" : "Current Request URL" },
  373.         { "CurrentUserId", useChinese ? "当前用户ID" : "Current User ID" },
  374.         { "CurrentUserName", useChinese ? "当前用户名称" : "Current User Name" },
  375.         
  376.         // 服务地址信息
  377.         { "ServerAddress", useChinese ? "服务侦听地址" : "Server Address" },
  378.         { "ServerPort", useChinese ? "服务侦听端口" : "Server Port" },
  379.         { "ServiceListeningAddress", useChinese ? "服务监听地址" : "Service Listening Address" },
  380.         { "ServiceIPv4Address", useChinese ? "服务实例IP地址" : "Service IPv4 Address" },
  381.         { "ServicePort", useChinese ? "服务实例端口" : "Service Port" },
  382.         
  383.         // 请求信息
  384.         { "RequestPath", useChinese ? "当前请求路径" : "Request Path" },
  385.         { "RequestMethod", useChinese ? "当前请求方法" : "Request Method" },
  386.             { "OSInformation", useChinese ? "操作系统信息" : "OS Information" },
  387. { "RuntimeVersion", useChinese ? ".NET运行时版本" : "Runtime Version" },
  388. { "ProcessId", useChinese ? "进程ID" : "Process ID" },
  389.     { "MemoryInfo.WorkingSet", useChinese ? "工作集(MB)" : "Working Set (MB)" },
  390.         { "MemoryInfo.PrivateMemorySize", useChinese ? "私有内存(MB)" : "Private Memory Size (MB)" },
  391.         { "MemoryInfo.VirtualMemorySize", useChinese ? "虚拟内存(MB)" : "Virtual Memory Size (MB)" },
  392.         { "MemoryInfo.PeakWorkingSet", useChinese ? "峰值工作集(MB)" : "Peak Working Set (MB)" },
  393.         { "MemoryInfo.PeakPrivateMemorySize", useChinese ? "峰值私有内存(MB)" : "Peak Private Memory Size (MB)" },
  394.         { "MemoryInfo.PeakVirtualMemorySize", useChinese ? "峰值虚拟内存(MB)" : "Peak Virtual Memory Size (MB)" },
  395.     };
  396.         // 初始化结果字典
  397.         var result = new Dictionary<string, object>();
  398.         // 添加环境与应用信息
  399.         result.Add("ApplicationName", ApplicationName);
  400.         result.Add("EnvironmentName", EnvironmentName);
  401.         result.Add("ContentRootPath", ContentRootPath);
  402.         result.Add("WebRootPath", WebRootPath);
  403.         result.Add("ServiceStartTime", ServiceStartTime);
  404.         result.Add("ServiceUptime", ServiceUptime);
  405.         result.Add("IsDevelopment", IsDevelopment);
  406.         result.Add("IsProduction", IsProduction);
  407.         // 添加客户端信息
  408.         result.Add("ClientIPv4Address", ClientIPv4Address);
  409.         result.Add("ClientPort", ClientPort);
  410.         result.Add("CurrentRequestUrl", CurrentRequestUrl);
  411.         result.Add("CurrentUserId", CurrentUserId);
  412.         result.Add("CurrentUserName", CurrentUserName);
  413.         // 添加服务地址信息
  414.         result.Add("ServerAddress", ServerAddress);
  415.         result.Add("ServerPort", ServerPort);
  416.         result.Add("ServiceListeningAddress", ServiceListeningAddress);
  417.         result.Add("ServiceIPv4Address", ServiceIPv4Address);
  418.         result.Add("ServicePort", ServicePort);
  419.         // 添加请求信息
  420.         result.Add("RequestPath", RequestPath);
  421.         result.Add("RequestMethod", RequestMethod);
  422.         result.Add("OSInformation", OSInformation);
  423.         result.Add("RuntimeVersion", RuntimeVersion);
  424.         result.Add("ProcessId", ProcessId);
  425.         // 内存信息添加逻辑
  426.         var memoryInfo = GetMemoryInfo();
  427.         result.Add("MemoryInfo.WorkingSet", memoryInfo.WorkingSet);
  428.         result.Add("MemoryInfo.PrivateMemorySize", memoryInfo.PrivateMemorySize);
  429.         result.Add("MemoryInfo.VirtualMemorySize", memoryInfo.VirtualMemorySize);
  430.         result.Add("MemoryInfo.PeakWorkingSet", memoryInfo.PeakWorkingSet);
  431.         result.Add("MemoryInfo.PeakPrivateMemorySize", memoryInfo.PeakPrivateMemorySize);
  432.         result.Add("MemoryInfo.PeakVirtualMemorySize", memoryInfo.PeakVirtualMemorySize);
  433.         // 转换为显示名称并返回
  434.         return result.ToDictionary(
  435.             kvp => displayNames[kvp.Key],
  436.             kvp => kvp.Value
  437.         );
  438.     }
  439. }
复制代码
  1. var builder = WebApplication.CreateBuilder(args);
  2. // Add services to the container.
  3. builder.Services.AddControllers();
  4. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
  5. builder.Services.AddEndpointsApiExplorer();
  6. builder.Services.AddSwaggerGen();
  7. builder.Services.AddHttpContextAccessor();
  8. var app = builder.Build();
  9. // Configure the HTTP request pipeline.
  10. if (app.Environment.IsDevelopment())
  11. {
  12.     app.UseSwagger();
  13.     app.UseSwaggerUI();
  14. }
  15. //初始化服务
  16. GlobalService.Initialize(app.Services);
  17. app.UseHttpsRedirection();
  18. app.UseAuthorization();
  19. app.MapControllers();
  20. app.Run();
复制代码
  1. [HttpGet]
  2. public IActionResult GetAllDisplayInfoApi()
  3. {
  4.         var serverAddress = GlobalService.GetAllDisplayInfo(true);
  5.         return Ok(serverAddress);
  6. }
复制代码
1.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册