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