我想使用DataAnnotations来验证实现某些接口的类,因此我将验证属性添加到接口,如下所示:
public interface IUser
{
[Required]
string Name { get; set; }
[Display(Name = "Email Address")]
[Required]
string Email { get; set; }
}
当我尝试使用Validator.TryValidateObject
时,它无效。
有没有办法做到这一点而不必编写自定义TryValidateObject
方法?
答案 0 :(得分:40)
我很惊讶没有人提到MetadataTypeAttribute。但是,这很有效。
[MetadataType(typeof(ICustomerMetaData))]
public partial class Customer
{
}
public interface ICustomerMetaData
{
// Apply RequiredAttribute
[Required(ErrorMessage = "Title is required.")]
string Title { get; }
}
至于直接使用接口(使用Customer: ICustomerMetaData
):
产品团队不希望实现此功能,原因有两个:
•与DataAnnotations.Validator的一致性
•与ASP.Net MVC中的验证行为保持一致
•棘手的场景:一个类实现了两个具有相同属性但具有相互冲突属性的接口。哪个属性优先?
虽然MVC自动使用TypeDescriptor注册MetaData,但您可能必须自己手动添加:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class Program
{
public static void Main()
{
var customer = new Customer();
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Customer),
typeof(ICustomerMetaData)),
typeof(Customer));
var context = new ValidationContext(customer);
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(
customer, context, validationResults, true);
Console.WriteLine($"is Valid = {isValid}");
customer.Title = "I has Title";
isValid = Validator.TryValidateObject(
customer, context, validationResults, true);
Console.WriteLine($"is Valid = {isValid}");
Console.ReadKey();
}
[MetadataType(typeof(ICustomerMetaData))]
public partial class Customer
{
public string Title { get; set; }
}
public interface ICustomerMetaData
{
// Apply RequiredAttribute
[Required(ErrorMessage = "Title is required.")]
string Title { get; }
}
}
输出:
有效=错误
是有效=真
答案 1 :(得分:4)
如果使用基类而不是接口,则属性可以正常工作。