自定义通用验证注释c#

本文关键字:注释 验证 自定义 | 更新日期: 2023-09-27 18:13:30

我需要编写一个通用验证注释,根据集合中对象的某些属性检查集合中的所有元素是否唯一。

例如,它需要验证任务列表中的所有任务名都是唯一的:

class Task
{
   public string TaskName {get; set;}
   public bool TaskIsComplete {get; set;}
   ...
}
[UniqueElementsRequired(ErrorMessage = "Task names must be unique")]
List<Task> TaskList {get; set;}

问题是它必须是通用的,所以我不知道如何指定使用什么属性作为构成"唯一"的决定性因素。

基本上我想这样做:

[UniqueElementsRequired(TaskList.Select(x => x.TaskName), ErrorMessage = "Task names must be unique")]
List<Task> TaskList {get; set;}

我可以直接使用任务名称列表。然而,我找不到一种方法来传递这样一个额外的列表

自定义通用验证注释c#

经过一些搜索和实验,我找到了一种方法来访问存储在我试图从验证注释中验证的集合中的对象的属性。诀窍在于构造函数并获得所需的PropertyInfo。要保持它的一般化有点棘手。

public class UniqueElementsRequiredAttribute : ValidationAttribute
{
    /// <summary>
    /// Initializes a new instance of the UniqueElementsRequiredAttribute class.
    /// </summary>
    /// <param name="typeOfCollectionElements">Type of the elements in the collection. Leave as null if testing the elements directly rather than one of their properties.</param>
    /// <param name="nameOfPropertyToTestForUniqueness">Name of element property desired to be unique. Leave as null if testing the elements directly rather than one of their properties. MUST BE EXACT.</param>
    public UniqueElementsRequiredAttribute(Type typeOfCollectionElements = null, string nameOfPropertyToTestForUniqueness = null)
    {
        NameOfPropertyToTestForUniqueness = nameOfPropertyToTestForUniqueness;
        TypeOfCollectionElements = typeOfCollectionElements;
    }
    private string NameOfPropertyToTestForUniqueness { get; set; }
    private Type TypeOfCollectionElements { get; set; }
    public override bool IsValid(object value)
    {
        var collection = value as IEnumerable;
        if (collection == null)
        {
            return true;
        }
        var listToTestForUniqueness = CreateListToTestForUniqueness(collection);
        int countOfAllElements = listToTestForUniqueness.Count();
        int countOfDistinctElements = listToTestForUniqueness.Distinct().Count();
        return countOfAllElements == countOfDistinctElements;
    }
    private List<object> CreateListToTestForUniqueness(IEnumerable collection)
    {
        var listToTestForUniqueness = new List<object>();
        if (NameOfPropertyToTestForUniqueness != null && TypeOfCollectionElements != null)
        {
// Trick 1
            PropertyInfo propertyInfoOfPropertyToTestForUniqueness = TypeOfCollectionElements.GetProperty(NameOfPropertyToTestForUniqueness);
            foreach (var element in collection)
            {
// Trick 2
                listToTestForUniqueness.Add(propertyInfoOfPropertyToTestForUniqueness.GetValue(element));
            }
        }
        else
        {
            listToTestForUniqueness = collection.Cast<object>().ToList();
        }
        return listToTestForUniqueness;
    }
}

验证注释应该这样标记:

    [UniqueElementsRequired(typeof(Task), "TaskName", ErrorMessage = "Task names must be unique")]
    public object TaskList { get; set; }

如果有人能想到一个更优雅的方法来解决这个问题,请告诉我,但它目前为止是有效的。