“RequiredAsSet”验证属性

时间:2010-09-24 10:57:30

标签: c# attributes data-annotations

我在我的应用程序中使用数据注释属性进行验证,并且我想要一个RequiredAsSet属性,这将要求填充所有使用该属性修饰的属性,或者不需要填充任何属性。该集合不能填充部分。

我认为一个聪明的方法就是这样:

public class RequiredAsSetAttribute : RequiredAttribute
{
    /// <summary>
    /// Initializes a new instance of the <see cref="RequiredAsSetAttribute"/> class.
    /// </summary>
    /// <param name="viewModel">The view model.</param>
    public RequiredAsSetAttribute(IViewModel viewModel)
    {
        this.ViewModel = viewModel;
    }

    /// <summary>
    /// Gets or sets the view model.
    /// </summary>
    /// <value>The view model.</value>
    private IViewModel ViewModel { get; set; }

    /// <summary>
    /// Determines whether the specified value is valid.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns>
    ///  <c>true</c> if the specified value is valid; otherwise, <c>false</c>.
    /// </returns>
    public override bool IsValid(object value)
    {
        IEnumerable<PropertyInfo> properties = GetPropertiesWihRequiredAsSetAttribute();
        bool aValueHasBeenEnteredInTheRequiredFieldSet = properties.Any(property => !string.IsNullOrEmpty(property.GetValue(this.ViewModel, null).ToString()));
        if (aValueHasBeenEnteredInTheRequiredFieldSet)
        {
            return base.IsValid(value);
        }

        return true;
    }

    /// <summary>
    /// Gets the properties with required as set attribute.
    /// </summary>
    /// <returns></returns>
    private IEnumerable<PropertyInfo> GetPropertiesWithRequiredAsSetAttribute()
    {
        return this.ViewModel.GetType()
            .GetProperties()
            .Where(p => GetValidatorsFromProperty(p).Length != 0 && !GetValidatorsFromProperty(p).Any(x => x == this));                
    }

    /// <summary>
    /// Gets the validators from property.
    /// </summary>
    /// <param name="property">The property.</param>
    /// <returns></returns>
    private static RequiredAsSetAttribute[] GetValidatorsFromProperty(PropertyInfo property)
    {
        return (RequiredAsSetAttribute[])property.GetCustomAttributes(typeof(RequiredAsSetAttribute), true);
    }
}

它基本上将我的视图模型作为构造函数参数,并使用反射来查找用RequiredAsSet属性修饰的其他属性,以检查是否输入了任何内容。

事实证明,这不是一个聪明的想法,因为你无法将实例传递给属性的构造函数。只有常量表达式,类型表达式或数组创建表达式,正如编译器有用地指出的那样。

还有另一种方法吗?

1 个答案:

答案 0 :(得分:0)

如果我理解问题是正确的,那么执行此操作的方法是使用类级别验证属性。然后,您可以访问整个对象,并可以使用反射来访问您希望的任何属性。在验证期间传入实例。

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class RequiredAsSetAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var properties = TypeDescriptor.GetProperties(value);
        ...
    }
}