using NCC; using NCC.ConfigurableOptions; using NCC.Dependency; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using System; using System.Linq; using System.Reflection; namespace Microsoft.Extensions.DependencyInjection { /// /// 可变选项服务拓展类 /// [SuppressSniffer] public static class ConfigurableOptionsServiceCollectionExtensions { /// /// 添加选项配置 /// /// 选项类型 /// 服务集合 /// 服务集合 public static IServiceCollection AddConfigurableOptions(this IServiceCollection services) where TOptions : class, IConfigurableOptions { var optionsType = typeof(TOptions); var optionsSettings = optionsType.GetCustomAttribute(false); // 获取配置路径 var path = GetConfigurationPath(optionsSettings, optionsType); // 配置选项(含验证信息) var configurationRoot = App.Configuration; var optionsConfiguration = configurationRoot.GetSection(path); // 配置选项监听 if (typeof(IConfigurableOptionsListener).IsAssignableFrom(optionsType)) { var onListenerMethod = optionsType.GetMethod(nameof(IConfigurableOptionsListener.OnListener)); if (onListenerMethod != null) { // 这里监听的是全局配置(总感觉不对头) ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () => { var options = optionsConfiguration.Get(); onListenerMethod.Invoke(options, new object[] { options, optionsConfiguration }); }); } } var optionsConfigure = services.AddOptions() .Bind(optionsConfiguration, options => { options.BindNonPublicProperties = true; // 绑定私有变量 }) .ValidateDataAnnotations(); // 配置复杂验证后后期配置 var validateInterface = optionsType.GetInterfaces() .FirstOrDefault(u => u.IsGenericType && typeof(IConfigurableOptions).IsAssignableFrom(u.GetGenericTypeDefinition())); if (validateInterface != null) { var genericArguments = validateInterface.GenericTypeArguments; // 配置复杂验证 if (genericArguments.Length > 1) { services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IValidateOptions), genericArguments.Last())); } // 配置后期配置 var postConfigureMethod = optionsType.GetMethod(nameof(IConfigurableOptions.PostConfigure)); if (postConfigureMethod != null) { if (optionsSettings?.PostConfigureAll != true) optionsConfigure.PostConfigure(options => postConfigureMethod.Invoke(options, new object[] { options, optionsConfiguration })); else services.PostConfigureAll(options => postConfigureMethod.Invoke(options, new object[] { options, optionsConfiguration })); } } return services; } /// /// 获取配置路径 /// /// 选项配置特性 /// 选项类型 /// private static string GetConfigurationPath(OptionsSettingsAttribute optionsSettings, Type optionsType) { // 默认后缀 var defaultStuffx = nameof(Options); return optionsSettings switch { // // 没有贴 [OptionsSettings],如果选项类以 `Options` 结尾,则移除,否则返回类名称 null => optionsType.Name.EndsWith(defaultStuffx) ? optionsType.Name[0..^defaultStuffx.Length] : optionsType.Name, // 如果贴有 [OptionsSettings] 特性,但未指定 Path 参数,则直接返回类名,否则返回 Path _ => optionsSettings != null && string.IsNullOrWhiteSpace(optionsSettings.Path) ? optionsType.Name : optionsSettings.Path, }; } } }