【发布时间】:2020-10-16 08:35:30
【问题描述】:
我创建了一个自定义验证属性,我想将它用于我的 API 控制器 DTO。该属性需要来自已配置选项的值,这就是我将它们注入构造函数的原因,以便稍后在IsValid 和FormatErrorMessage 方法中使用选项服务。
internal class MyValidationAttribute : ValidationAttribute
{
private readonly IOptionsMonitor<MyOptions> myOptionsMonitor;
public MyValidationAttribute(IOptionsMonitor<MyOptions> myOptionsMonitor)
{
this.myOptionsMonitor = myOptionsMonitor;
}
public override bool IsValid(object value)
{
// ... use myOptionsMonitor here ...
return false;
}
public override string FormatErrorMessage(string name)
{
// ... use myOptionsMonitor here ...
return string.Empty;
}
}
不幸的是,当我想在我的 DTO 中使用它作为属性时
internal class MyDTO
{
[MyValidationAttribute]
public string Foo { get; set; }
}
我收到错误消息
没有给出与所需形式相对应的参数 参数“myOptionsMonitor”的 'MyValidationAttribute.MyValidationAttribute(IOptionsMonitor)'
有没有办法可以使用依赖注入来验证属性?我知道我可以像这样使用ValidationContext
internal class MyValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
IOptionsMonitor<MyOptions> myOptionsMonitor = validationContext.GetService<IOptionsMonitor<MyOptions>>();
// ...
return ValidationResult.Success;
}
return new ValidationResult("Something failed");
}
}
但我想使用基类中的FormatErrorMessage 方法,而这无法访问选项服务。
我目前的解决方案
目前,这是我正在使用的代码
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
internal class CustomValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
IOptionsMonitor<MyOptions> myOptionsMonitor = validationContext.GetService<IOptionsMonitor<MyOptions>>();
Dictionary<string, string> myMap = myOptionsMonitor.CurrentValue.MyMap;
string key = value.ToString() ?? string.Empty;
if (myMap.ContainsKey(key))
return ValidationResult.Success;
string[] formattedKeys = myMap.Keys.Select(key => $"'{key}'").ToArray();
string keysText = string.Join(" / ", formattedKeys);
string errorMessage = $"Invalid value. Valid ones are {keysText}";
return new ValidationResult(errorMessage);
}
}
【问题讨论】:
-
属性给类型添加元数据信息,为什么你认为可以给它注入一些东西?
-
我认为依赖注入可以在任何地方使用。那你知道如何注入服务吗?
-
例如,您能在静态构造函数中使用 DI 吗?
-
对不起,你什么意思?
-
请不要将您的解决方案编辑到您的问题中。相反,将其发布为问题的自我答案。
标签: c# .net-core asp.net-core-webapi data-annotations