我想使用 .NET StringLength 和 Range 属性对我的类中的各种属性施加约束。我写了以下非常简单的代码:
class AttributePlayground
{
[StringLength(5)]
public static String StringLengthTest { get; set; }
[Range(10, 20)]
public static int Age { get; set; }
}
static void Main(string[] args)
{
AttributePlayground.StringLengthTest = "Too long!";
AttributePlayground.Age = 34;
}
我预计会发生错误或异常,但一切正常。
我在网上看到的有关这些属性的所有示例都在 MVC 上下文中显示了它们,但文档没有引用它。
如您所知,.NET 中的属性只是在编译时嵌入到程序集中的元数据。如果没有任何东西可以解释它们,那么什么也不会发生。
因此,以 ASP.NET MVC 为例,有一个验证器可以解释这些属性,如下所示:
class AttributePlayground
{
[StringLength(5)]
public String StringLengthTest { get; set; }
[Range(10, 20)]
public int Age { get; set; }
}
class Program
{
static void Main()
{
var attributePlayground = new AttributePlayground();
attributePlayground.StringLengthTest = "Too long!";
attributePlayground.Age = 34;
var context = new ValidationContext(attributePlayground, null, null);
var errors = new List<ValidationResult>();
if (!Validator.TryValidateObject(attributePlayground, context, errors, true))
{
foreach (var error in errors)
{
Console.WriteLine(error.ErrorMessage);
}
}
}
}
但老实说,如果您打算进行一些更严肃和复杂的验证,我建议您不要使用声明性验证逻辑,这就是数据注释。我会推荐您FluentValidation.NET。它允许您以一种很好的方式表达更复杂的验证规则,否则使用数据注释很难实现。
是的,这是可能的。这是一个老问题,但谷歌搜索让我来到这里,我将为未来的读者留下答案。 如果您在 ASP 之外,则需要自己调用验证器。这是如何做到的:
using System;
using System.Globalization;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
class AttributePlayground
{
private String _stringLengthTest;
[StringLength(5)]
public String StringLengthTest {
get { return _stringLengthTest; }
set { _stringLengthTest = value; ValidateProperty("StringLengthTest"); }
}
private int _age;
[Range(10, 20)]
public int Age {
get { return _age; }
set { _age = value; ValidateProperty("Age"); }
}
private void ValidateProperty(string propName)
{
PropertyInfo propInfo = this.GetType().GetProperty(propName);
Object[] attributes = propInfo.GetCustomAttributes(true);
foreach (Object attribute in attributes)
{
ValidationAttribute vattr = attribute as ValidationAttribute;
if (vattr != null)
{
object propValue = propInfo.GetValue(this, null);
vattr.Validate(propValue, propInfo.Name);
}
}
}
}
每当在属性分配期间遇到属性限制时,这都会产生一个很好的 ValidationException。如果您愿意,可以将验证方法设为静态并传递
this
作为参数。
另请参阅这个问题,了解如何使用 DataAnnotations.Validator 类手动验证。
这不在问题范围内,但也可以使用自定义属性。这是一个简短的例子:
// Introduce the [StringLengthIs(number)] attribute:
sealed public class StringLengthIsAttribute : ValidationAttribute
{
public int Length { get; private set; }
public StringLengthIsAttribute(int len)
{
ErrorMessage = "The field {0} must be a string with a length of {1}.";
Length = len;
}
public override bool IsValid(object value)
{
if (value == null) return false;
return value.ToString().Length == Length;
}
public override string FormatErrorMessage(string name)
{
return string.Format(CultureInfo.CurrentCulture,
ErrorMessageString, name, Length);
}
}