如何创build自定义validation属性?
我想创build一个自定义的validation属性,我想在我的模型类中比较我的属性的值与另一个属性的值。 例如,我在我的模型类中:
... public string SourceCity { get; set; } public string DestinationCity { get; set; }
而我想创build一个自定义属性来使用它,像这样:
[Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] public string DestinationCity { get; set; } //this wil lcompare SourceCity with DestinationCity
我如何到那里?
以下是如何获得其他属性值:
public class CustomAttribute : ValidationAttribute { private readonly string _other; public CustomAttribute(string other) { _other = other; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var property = validationContext.ObjectType.GetProperty(_other); if (property == null) { return new ValidationResult( string.Format("Unknown property: {0}", _other) ); } var otherValue = property.GetValue(validationContext.ObjectInstance, null); // at this stage you have "value" and "otherValue" pointing // to the value of the property on which this attribute // is applied and the value of the other property respectively // => you could do some checks if (!object.Equals(value, otherValue)) { // here we are verifying whether the 2 values are equal // but you could do any custom validation you like return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } return null; } }
请看下面的例子:
模型类实现INotifyPropertyChanged
public class ModelClass : INotifyPropertyChanged { private string destinationCity; public string SourceCity { get; set; } public ModelClass() { PropertyChanged += CustomAttribute.ThrowIfNotEquals; } [Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] public string DestinationCity { get { return this.destinationCity; } set { if (value != this.destinationCity) { this.destinationCity = value; NotifyPropertyChanged("DestinationCity"); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void NotifyPropertyChanged(string info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } }
属性类还包含事件hendler。
internal sealed class CustomAttribute : Attribute { public CustomAttribute(string propertyName) { PropertyName = propertyName; } public string PropertyName { get; set; } public string ErrorMessage { get; set; } public static void ThrowIfNotEquals(object obj, PropertyChangedEventArgs eventArgs) { Type type = obj.GetType(); var changedProperty = type.GetProperty(eventArgs.PropertyName); var attribute = (CustomAttribute)changedProperty .GetCustomAttributes(typeof(CustomAttribute), false) .FirstOrDefault(); var valueToCompare = type.GetProperty(attribute.PropertyName).GetValue(obj, null); if (!valueToCompare.Equals(changedProperty.GetValue(obj, null))) throw new Exception("the source and destination should not be equal"); } }
用法
var test = new ModelClass(); test.SourceCity = "1"; // Everything is ok test.DestinationCity = "1"; // throws exception test.DestinationCity ="2";
为了简化代码,我决定省略validation。
最好的方法是通过IValidatableObject。 请参阅http://msdn.microsoft.com/en-us/data/gg193959.aspx