/// <summary>
/// Specifies that the field must compare favourably with the
named field, if objects to check are not of the same type
/// false will be return
/// </summary>
public class CompareValuesAttribute :
ValidationAttribute
{
/// <summary>
/// The other property to compare to
/// </summary>
public string OtherProperty { get; set; }
public CompareValues Criteria { get; set;
}
/// <summary>
/// Creates the attribute
/// </summary>
/// <param name="otherProperty">The other
property to compare to</param>
public CompareValuesAttribute(string
otherProperty, CompareValues criteria)
{
if (otherProperty == null)
throw new
ArgumentNullException("otherProperty");
OtherProperty =
otherProperty;
Criteria = criteria;
}
/// <summary>
/// Determines whether the specified value of
the object is valid. For this to be the case, the objects must be of the
same type
/// and satisfy the comparison criteria. Null
values will return false in all cases except when both
/// objects are null. The objects will
need to implement IComparable for the GreaterThan,LessThan,GreatThanOrEqualTo
and LessThanOrEqualTo instances
/// </summary>
/// <param name="value">The value of the
object to validate</param>
/// <param name="validationContext">The
validation context</param>
/// <returns>A validation result if the
object is invalid, null if the object is valid</returns>
protected override ValidationResult
IsValid(object value, ValidationContext validationContext)
{
// the the other property
var property =
validationContext.ObjectType.GetProperty(OtherProperty);
// check it is not null
if (property == null)
return new
ValidationResult(String.Format("Unknown property: {0}.", OtherProperty));
// check types
var memberName =
validationContext.ObjectType.GetProperties().Where(p =>
p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name
== validationContext.DisplayName)).Select(p =>
p.Name).FirstOrDefault();
if (memberName == null)
{
memberName =
validationContext.DisplayName;
}
if
(validationContext.ObjectType.GetProperty(memberName).PropertyType !=
property.PropertyType)
return new
ValidationResult(String.Format("The types of {0} and {1} must be the same.",
memberName, OtherProperty));
// get the other value
var other =
property.GetValue(validationContext.ObjectInstance, null);
// equals to comparison,
if (Criteria ==
CompareValues.EqualTo)
{
if
(Object.Equals(value, other))
return null;
}
else if (Criteria ==
CompareValues.NotEqualTo)
{
if
(!Object.Equals(value, other))
return null;
}
else
{
// check that both
objects are IComparables
if (!(value is
IComparable) || !(other is IComparable))
return new ValidationResult(String.Format("{0} and {1} must both implement
IComparable", validationContext.DisplayName, OtherProperty));
// compare the
objects
var result =
Comparer.Default.Compare(value, other);
switch
(Criteria)
{
case
CompareValues.GreaterThan:
if (result > 0)
return null;
break;
case
CompareValues.LessThan:
if (result < 0)
return null;
break;
case
CompareValues.GreatThanOrEqualTo:
if (result >= 0)
return null;
break;
case
CompareValues.LessThanOrEqualTo:
if (result <= 0)
return null;
break;
}
}
// got this far must mean the
items don‘t meet the comparison criteria
return new
ValidationResult(ErrorMessage);
}
}
/// <summary>
/// Indicates a comparison criteria used by the CompareValues
attribute
/// </summary>
public enum CompareValues
{
EqualTo,
NotEqualTo,
GreaterThan,
LessThan,
GreatThanOrEqualTo,
LessThanOrEqualTo
}
复制代码
应用的时候直接在指定的属性上添加此CompareValuesAttribute标签即可
【注:第一个参数是要与之比较的属性名,第二个参数表示两个属性值之间的大小关系,第三个参数表示错误提示信息】
复制代码
public class EricSunModel
{
[Display(Name = "Ready Time")]
public string ReadyTime { get; set; }
[CompareValues("ReadyTime", CompareValues.GreaterThan,
ErrorMessage = "Close time must be later than ready time")]
[Display(Name = "Close Time")]
public string CloseTime { get; set; }