ConfigurableOptionsServiceCollectionExtensions.cs
4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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
{
/// <summary>
/// 可变选项服务拓展类
/// </summary>
[SuppressSniffer]
public static class ConfigurableOptionsServiceCollectionExtensions
{
/// <summary>
/// 添加选项配置
/// </summary>
/// <typeparam name="TOptions">选项类型</typeparam>
/// <param name="services">服务集合</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddConfigurableOptions<TOptions>(this IServiceCollection services)
where TOptions : class, IConfigurableOptions
{
var optionsType = typeof(TOptions);
var optionsSettings = optionsType.GetCustomAttribute<OptionsSettingsAttribute>(false);
// 获取配置路径
var path = GetConfigurationPath(optionsSettings, optionsType);
// 配置选项(含验证信息)
var configurationRoot = App.Configuration;
var optionsConfiguration = configurationRoot.GetSection(path);
// 配置选项监听
if (typeof(IConfigurableOptionsListener<TOptions>).IsAssignableFrom(optionsType))
{
var onListenerMethod = optionsType.GetMethod(nameof(IConfigurableOptionsListener<TOptions>.OnListener));
if (onListenerMethod != null)
{
// 这里监听的是全局配置(总感觉不对头)
ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () =>
{
var options = optionsConfiguration.Get<TOptions>();
onListenerMethod.Invoke(options, new object[] { options, optionsConfiguration });
});
}
}
var optionsConfigure = services.AddOptions<TOptions>()
.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<TOptions>), genericArguments.Last()));
}
// 配置后期配置
var postConfigureMethod = optionsType.GetMethod(nameof(IConfigurableOptions<TOptions>.PostConfigure));
if (postConfigureMethod != null)
{
if (optionsSettings?.PostConfigureAll != true)
optionsConfigure.PostConfigure(options => postConfigureMethod.Invoke(options, new object[] { options, optionsConfiguration }));
else
services.PostConfigureAll<TOptions>(options => postConfigureMethod.Invoke(options, new object[] { options, optionsConfiguration }));
}
}
return services;
}
/// <summary>
/// 获取配置路径
/// </summary>
/// <param name="optionsSettings">选项配置特性</param>
/// <param name="optionsType">选项类型</param>
/// <returns></returns>
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,
};
}
}
}