Blame view

netcore/src/Infrastructure/NCC/ConfigurableOptions/Extensions/ConfigurableOptionsServiceCollectionExtensions.cs 4.71 KB
de2bd2f9   “wangming”   项目初始化
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,
              };
          }
      }
  }