C# &引用;“所需资产”;验证属性

C# &引用;“所需资产”;验证属性,c#,attributes,data-annotations,C#,Attributes,Data Annotations,我在我的应用程序中使用数据注释属性进行验证,我希望有一个RequiredAsSet属性,它将要求填充用该属性修饰的所有属性,或者不填充任何属性。无法部分填充该集合 我认为一个聪明的方法是这样的: public class RequiredAsSetAttribute : RequiredAttribute { /// <summary> /// Initializes a new instance of the <see cref="RequiredAsSetA

我在我的应用程序中使用数据注释属性进行验证,我希望有一个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);
    }
}
公共类RequiredAsSetAttribute:RequiredAttribute
{
/// 
///初始化类的新实例。
/// 
///视图模型。
公共所需资产属性(IViewModel viewModel)
{
this.ViewModel=ViewModel;
}
/// 
///获取或设置视图模型。
/// 
///视图模型。
私有IViewModel视图模型{get;set;}
/// 
///确定指定的值是否有效。
/// 
///价值。
/// 
///如果指定的值有效,则为true;否则为false。
/// 
公共覆盖布尔值有效(对象值)
{
IEnumerable properties=GetPropertiesWihRequiredAsSetAttribute();
bool avaluehasbeenteredintererequired字段集=properties.Any(property=>!string.IsNullOrEmpty(property.GetValue(this.ViewModel,null.ToString());
如果(所需字段集中已输入AVALUE)
{
返回base.IsValid(值);
}
返回true;
}
/// 
///获取具有required as set属性的属性。
/// 
/// 
private IEnumerable GetProperties with RequiredAssetAttribute()
{
返回此.ViewModel.GetType()
.GetProperties()
其中(p=>GetValidatorsFromProperty(p).Length!=0&&!GetValidatorsFromProperty(p).Any(x=>x==this));
}
/// 
///从属性获取验证程序。
/// 
///财产。
/// 
私有静态RequiredAsSetAttribute[]GetValidatorsFromProperty(PropertyInfo属性)
{
return(RequiredAsSetAttribute[])属性。GetCustomAttributes(typeof(RequiredAsSetAttribute),true;
}
}
它基本上将我的视图模型作为构造函数参数,并使用反射来查找用RequiredAsSet属性修饰的其他属性,以检查是否输入了任何内容

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


那么还有别的方法吗

如果我正确理解了这个问题,那么实现这一点的方法是使用类级验证属性。然后,您可以访问整个对象,并可以使用反射来访问您想要的任何属性。在验证期间传入实例

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