using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace NCC
{
///
/// 内部 App 副本
///
internal static class InternalApp
{
///
/// 应用服务
///
internal static IServiceCollection InternalServices;
///
/// 根服务
///
internal static IServiceProvider RootServices;
///
/// 配置对象
///
internal static IConfiguration Configuration;
///
/// 获取Web主机环境
///
internal static IWebHostEnvironment WebHostEnvironment;
///
/// 获取泛型主机环境
///
internal static IHostEnvironment HostEnvironment;
///
/// 配置 NCC 框架(Web)
///
///
internal static void ConfigureApplication(IWebHostBuilder builder)
{
// 自动装载配置
builder.ConfigureAppConfiguration((hostContext, configurationBuilder) =>
{
// 存储环境对象
HostEnvironment = WebHostEnvironment = hostContext.HostingEnvironment;
// 加载配置
AddJsonFiles(configurationBuilder, hostContext.HostingEnvironment);
});
// 应用初始化服务
builder.ConfigureServices((hostContext, services) =>
{
// 存储配置对象
Configuration = hostContext.Configuration;
// 存储服务提供器
InternalServices = services;
// 注册 Startup 过滤器
services.AddTransient();
// 注册 HttpContextAccessor 服务
services.AddHttpContextAccessor();
// 初始化应用服务
services.AddApp();
});
}
///
/// 配置 NCC 框架(非 Web)
///
///
///
internal static void ConfigureApplication(IHostBuilder builder, bool autoRegisterBackgroundService = true)
{
builder.ConfigureAppConfiguration((hostContext, configurationBuilder) =>
{
// 存储环境对象
HostEnvironment = hostContext.HostingEnvironment;
// 加载配置
AddJsonFiles(configurationBuilder, hostContext.HostingEnvironment);
});
// 自动注入 AddApp() 服务
builder.ConfigureServices((hostContext, services) =>
{
// 存储配置对象
Configuration = hostContext.Configuration;
// 存储服务提供器
InternalServices = services;
// 存储根服务
services.AddHostedService();
// 初始化应用服务
services.AddApp();
// 自动注册 BackgroundService
if (autoRegisterBackgroundService) services.AddAppHostedService();
});
}
///
/// 加载自定义 .json 配置文件
///
///
///
internal static void AddJsonFiles(IConfigurationBuilder configurationBuilder, IHostEnvironment hostEnvironment)
{
// 获取根配置
var configuration = configurationBuilder.Build();
// 获取程序执行目录
var executeDirectory = AppContext.BaseDirectory;
// 获取自定义配置扫描目录
var configurationScanDirectories = (configuration.GetSection("ConfigurationScanDirectories")
.Get()
?? Array.Empty()).Select(u => Path.Combine(executeDirectory, u));
// 扫描执行目录及自定义配置目录下的 *.json 文件
var jsonFiles = new[] { executeDirectory }.Concat(configurationScanDirectories)
.SelectMany(u =>
Directory.GetFiles(u, "*.json", SearchOption.TopDirectoryOnly));
// 如果没有配置文件,中止执行
if (!jsonFiles.Any()) return;
// 获取环境变量名,如果没找到,则读取 NETCORE_ENVIRONMENT 环境变量信息识别(用于非 Web 环境)
var envName = hostEnvironment?.EnvironmentName ?? Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT") ?? "Unknown";
// 读取忽略的配置文件
var ignoreConfigurationFiles = configuration.GetSection("IgnoreConfigurationFiles")
.Get()
?? Array.Empty();
// 处理控制台应用程序
var _excludeJsonPrefixs = hostEnvironment == default ? excludeJsonPrefixs.Where(u => !u.Equals("appsettings")) : excludeJsonPrefixs;
// 将所有文件进行分组
var jsonFilesGroups = SplitConfigFileNameToGroups(jsonFiles)
.Where(u => !_excludeJsonPrefixs.Contains(u.Key, StringComparer.OrdinalIgnoreCase) && !u.Any(c => runtimeJsonSuffixs.Any(z => c.EndsWith(z, StringComparison.OrdinalIgnoreCase)) || ignoreConfigurationFiles.Contains(Path.GetFileName(c), StringComparer.OrdinalIgnoreCase)));
// 遍历所有配置分组
foreach (var group in jsonFilesGroups)
{
// 限制查找的 json 文件组
var limitFileNames = new[] { $"{group.Key}.json", $"{group.Key}.{envName}.json" };
// 查找默认配置和环境配置
var files = group.Where(u => limitFileNames.Contains(Path.GetFileName(u), StringComparer.OrdinalIgnoreCase))
.OrderBy(u => Path.GetFileName(u).Length);
// 循环加载
foreach (var jsonFile in files)
{
configurationBuilder.AddJsonFile(jsonFile, optional: true, reloadOnChange: true);
}
}
}
///
/// 排序的配置文件前缀
///
private static readonly string[] excludeJsonPrefixs = new[] { "appsettings", "bundleconfig", "compilerconfig" };
///
/// 排除运行时 Json 后缀
///
private static readonly string[] runtimeJsonSuffixs = new[]
{
"deps.json",
"runtimeconfig.dev.json",
"runtimeconfig.prod.json",
"runtimeconfig.json"
};
///
/// 对配置文件名进行分组
///
///
///
private static IEnumerable> SplitConfigFileNameToGroups(IEnumerable configFiles)
{
// 分组
return configFiles.GroupBy(Function);
// 本地函数
static string Function(string file)
{
// 根据 . 分隔
var fileNameParts = Path.GetFileName(file).Split('.', StringSplitOptions.RemoveEmptyEntries);
if (fileNameParts.Length == 2) return fileNameParts[0];
return string.Join('.', fileNameParts.Take(fileNameParts.Length - 2));
}
}
}
}