自定义通用验证注释c#

时间:2014-07-17 12:43:29

标签: c# generics annotations

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

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

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;}

我可以使用任务名称列表。但是我无法找到传递这样的附加列表的方法。

1 个答案:

答案 0 :(得分:0)

经过一些搜索和实验,我找到了一种方法来访问存储在集合中的对象的属性,我试图从验证注释中进行验证。诀窍是构造函数并获得您想要的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; }

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