Я использую атрибуты аннотаций данных для проверки в своем приложении и хочу иметь атрибут 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, чтобы проверить, было ли что-либо введено.
Оказывается, это не такая умная идея, потому что вы не можете передавать экземпляры в конструктор атрибута ... только константные выражения, выражения typeof или выражения создания массива, как подсказал компилятор.
Так есть ли другой способ сделать это?