重新整理 .net core 實踐篇—————3種配置驗證[十四]

不問前世 發表於 2021-06-08
.Net

前言

簡單整理一些配置的驗證。

正文

配置的驗證大概分為3類:

  1. 直接註冊驗證函式

  2. 實現IValidteOptions

  3. 使用Microsoft.Extensions.Options.DataAnnotations

直接註冊驗證函式

服務:

public class SelfService : ISelfService
{
	IOptionsMonitor<SelfServiceOption> _options;
	public SelfService(IOptionsMonitor<SelfServiceOption> options)
	{
		this._options = options;

		_options.OnChange((selftServiceOptions) =>
		{
			Console.WriteLine("alter change:" + selftServiceOptions.Name);
		});
	}
	public string ShowOptionName()
	{
		return _options.CurrentValue.Name;
	}
}

註冊:

services.Configure<SelfServiceOption>(Configuration.GetSection("SelfService"), BinderOptions =>
{
	BinderOptions.BindNonPublicProperties = true;
});
services.AddSingleton<ISelfService, SelfService>();
services.AddOptions<SelfServiceOption>().Validate(options =>
{
	return options.Name != "zhangsan";
});

配置:

{
    "SelfService": {
    "name": "zhangsan"
  }
}

測試:

[HttpGet]
public int GetService([FromServices]ISelfService selfService)
{
	Console.WriteLine(selfService.ShowOptionName());
	return 1;
}

結果:

重新整理 .net core 實踐篇—————3種配置驗證[十四]

使用Microsoft.Extensions.Options.DataAnnotations

services.AddOptions().ValidateDataAnnotations();

加上這個函式ValidateDataAnnotations。

然後我們的配置類上加一些屬性之類的:

public class SelfServiceOption
{
	[Required]
	[StringLength(5)]
	public string Name { get; set; }
}

因為zhangsan 這個字元超過了5。
結果:

重新整理 .net core 實踐篇—————3種配置驗證[十四]

實現IValidteOptions

書寫驗證函式:

public class SelfServiceValidateOptions : IValidateOptions<SelfServiceOption>
{

	public ValidateOptionsResult Validate(string name, SelfServiceOption options)
	{
		if (options.Name.Length >5)
		{
			return ValidateOptionsResult.Fail("Name長度不能大於5");
		}
		else
		{
			return ValidateOptionsResult.Success;
		}
	}
}

註冊進去:

services.AddSingleton<IValidateOptions,SelfServiceValidateOptions>();

結果:

![](https://img2020.cnblogs.com/blog/1289794/202106/1289794-20210606084403021-1632864116.png)

至於驗證的原理。

舉下面這個例子:

services.AddOptions<SelfServiceOption>().Validate(options =>
{
      return options.Name != "zhangsan";
});

檢視Validate:

public virtual OptionsBuilder<TOptions> Validate(Func<TOptions, bool> validation)
{
  return this.Validate(validation, "A validation error has occured.");
}

public virtual OptionsBuilder<TOptions> Validate(
  Func<TOptions, bool> validation,
  string failureMessage)
{
  if (validation == null)
	throw new ArgumentNullException(nameof (validation));
  this.Services.AddSingleton<IValidateOptions<TOptions>>((IValidateOptions<TOptions>) new ValidateOptions<TOptions>(this.Name, validation, failureMessage));
  return this;
}

就十二中也介紹了,在OptionFactory Create的函式中:

//這是_validations的型別
private readonly IEnumerable<IValidateOptions<TOptions>> _validations;
//下面是Create 函式部分:

if (_validations != null)
{
	var failures = new List<string>();
	foreach (var validate in _validations)
	{
		var result = validate.Validate(name, options);
		if (result.Failed)
		{
			failures.AddRange(result.Failures);
		}
	}
	if (failures.Count > 0)
	{
		throw new OptionsValidationException(name, typeof(TOptions), failures);
	}
}

會把我們的驗證全部驗證執行一遍,然後給出全部的錯誤,所以如果報錯的時候,應該把錯誤看齊,不是隻顯示一個錯誤,因為可能不止一個錯誤。

以上只是個人整理,如有錯誤,望請指點。

下一節,日誌系統之戰地記者

相關文章