如何使用.NET Core 选项模式【Options】

2020-07-01 13:00:16王冬梅

使用 DI 服务配置选项

在配置选项时,可以通过以下两种方式通过依赖关系注入访问服务:

将配置委托传递给 OptionsBuilder 上的 Configure
services.AddOptions<MyOptions>("optionalName")
  .Configure<Service1, Service2, Service3, Service4, Service5>(
    (o, s, s2, s3, s4, s5) => 
      o.Property = DoSomethingWith(s, s2, s3, s4, s5));
创建实现 IConfigureOptions 或 IConfigureNamedOptions 的类型,并将该类型注册为服务

建议将配置委托传递给 Configure,因为创建服务较复杂。 在调用 Configure 时,创建类型等效于框架执行的操作。 调用 Configure 会注册临时泛型 IConfigureNamedOptions,它具有接受指定的泛型服务类型的构造函数。

选项验证

appsettings.json 文件

{
 "MyConfig": {
  "Key1": "My Key One",
  "Key2": 10,
  "Key3": 32
 }
}

下面的类绑定到 "MyConfig" 配置节,并应用若干 DataAnnotations 规则:

public class MyConfigOptions
{
  public const string MyConfig = "MyConfig";

  [RegularExpression(@"^[a-zA-Z''-'s]{1,40}$")]
  public string Key1 { get; set; }
  [Range(0, 1000,
    ErrorMessage = "Value for {0} must be between {1} and {2}.")]
  public int Key2 { get; set; }
  public int Key3 { get; set; }
}
启用DataAnnotations验证
public void ConfigureServices(IServiceCollection services)
{
  services.AddOptions<MyConfigOptions>()
    .Bind(Configuration.GetSection(MyConfigOptions.MyConfig))
    .ValidateDataAnnotations();

  services.AddControllersWithViews();
}

使用IValidateOptions更复杂的配置

public class MyConfigValidation : IValidateOptions<MyConfigOptions>
{
  public MyConfigOptions _config { get; private set; }

  public MyConfigValidation(IConfiguration config)
  {
    _config = config.GetSection(MyConfigOptions.MyConfig)
      .Get<MyConfigOptions>();
  }

  public ValidateOptionsResult Validate(string name, MyConfigOptions options)
  {
    string vor=null;
    var rx = new Regex(@"^[a-zA-Z''-'s]{1,40}$");
    var match = rx.Match(options.Key1);

    if (string.IsNullOrEmpty(match.Value))
    {
      vor = $"{options.Key1} doesn't match RegEx n";
    }

    if ( options.Key2 < 0 || options.Key2 > 1000)
    {
      vor = $"{options.Key2} doesn't match Range 0 - 1000 n";
    }

    if (_config.Key2 != default)
    {
      if(_config.Key3 <= _config.Key2)
      {
        vor += "Key3 must be > than Key2.";
      }
    }

    if (vor != null)
    {
      return ValidateOptionsResult.Fail(vor);
    }

    return ValidateOptionsResult.Success;
  }
}

IValidateOptions 允许将验证代码移出 StartUp 并将其移入类中。

使用前面的代码,使用以下代码在 Startup.ConfigureServices 中启用验证

public void ConfigureServices(IServiceCollection services)
{
  services.Configure<MyConfigOptions>(Configuration.GetSection(
                    MyConfigOptions.MyConfig));
  services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions
               <MyConfigOptions>, MyConfigValidation>());
  services.AddControllersWithViews();
}