我正在尝试构建一系列属性类,以便我们的开发团队更轻松地验证对象。对象是像这样的POCO类。
public class User
{
public string Name { get; set; }
public string Company { get; set; }
}
我想用自定义属性修饰此模型。
public class User
{
[MustHaveValue]
public string Name { get; set; }
public string Company { get; set; }
}
然后我将创建自己的类,实现ValidationAttribute
,这是.NET Framework中的基类,属于System.ComponentModel.DataAnnotations
。
public class MustHaveValueAttribute : ValidationAttribute
{
.
.
public override IsValid(object value)
{
// validation logic.
}
}
然后我可以通过制作User
,ValidationContext
等实例集来随时验证List<ValidationResult>
模型。
但在企业环境中,问题不能通过特定的类来解决。我的验证方案需要更复杂,更灵活的方法。想象一下,所需的验证方案之一就是这样的。
public class User
{
public string Name { get; set; }
public string Company { get; set; }
// Check if an item exists in this list.
[MustHaveMoreThanOneItem]
public IList<Client> Clients { get; set; }
}
然后我需要创建另一个属性类
public class MustHaveMoreThanOneItemAttribute : ValidationAttribute
{
.
.
public override IsValid(object value)
{
// Let's assume this value is List<Client> for now.
// I know the exact type, so I'm going to cast it to List<Client> without further considerations
List<Client> clients = value as List<Client>;
if(clients.Count > 0) {
return true;
} else {
return false;
}
}
}
但问题是,还有很多其他模型都有嵌套列表项。试着想象一下我想在其他模型中重用MustHaveMoreThanOneItem
的时间,比如......
public class Department
{
public string Name { get; set; }
[MustHaveMoreThanOneItem]
public IList<Employee> { get; set; }
}
您已经知道它无法正常工作,因为它仅针对List<Client>
进行了强类型输入。所以我决定用Generic
来解决这个问题。
但令我失望的是,_Attribute
界面并不支持Generic
。没有像_Attribute<T> : Attribute
那样的额外实施,因此,没有ValidationAttribute<T>
唉!!我不能在这里使用Generic
!!
public class Department
{
public string Name { get; set; }
// No way to use this syntax.
[MustHaveMoreThanOneItem<Employee>]
public IList<Employee> { get; set; }
}
所以我得出结论,Attribute
必须是针对一组固定的验证而设计的,例如电子邮件格式,卡片格式,空格检查等IMAO。
但是我仍然想要使用一个属性并在其中提供很多灵活性,以防止像这样重复,冗长的验证代码。
if(model.Clients.Count > 0) ...
if(model.Name != null) ...
if(model.Clients.GroupBy(x => x.Country == Country.USA).Count >= 1) ...
if(model.Clients.Where(x => x.CompanyName == Company.Google).ToList().Count > 1 ) ...
.
.
.
我想在这里提出两个问题。
Attirbute
支持Generic
,这个问题会解决吗? Generic Attribute
?才能使用
关于班级成员的[MustHaveMoreThanOneItem<Employee>]
注释?答案 0 :(得分:2)
您可以通常检查实现IEnumerable
的任何对象:
public class MustHaveMoreThanOneItemAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// omitted null checking
var enumerable = value as IEnumerable;
var enumerator = enumerable.GetEnumerator();
if (!enumerator.MoveNext())
{
return false;
}
if (!enumerator.MoveNext())
{
return false;
}
return true;
}
}
答案 1 :(得分:2)
根据定义,C#不支持泛型类型属性,尽管这已被长期主动请求:
但是,您仍然可以通过构造函数将类型注入验证属性。然后,您可以使用反射或任何您需要的方法来定义自定义验证标准。
public class MustHaveMoreThanOneItemAttribute : ValidationAttribute
{
public Type EnumerableType { get; }
public MustHaveMoreThanOneItemAttribute(Type t)
=> this.EnumerableType = typeof(ICollection<>).MakeGenericType(t);
public override bool IsValid(object value)
{
var count = this.EnumerableType.GetProperty("Count").GetValue(value) as int?;
return (count ?? 0) > 1;
}
}
现在,您可以使用类似于目标的内容:
public class Department
{
public string Name { get; set; }
[MustHaveMoreThanOneItem(typeof(Employee))]
public IList<Employee> { get; set; }
}