namespace System.ComponentModel.DataAnnotations { using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Resources; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is designed to be a base class for other attributes.")] public class CompareAttribute : ValidationAttribute { public CompareAttribute(string otherProperty) : base(DataAnnotationsResources.CompareAttribute_MustMatch) { if (otherProperty == null) { throw new ArgumentNullException("otherProperty"); } OtherProperty = otherProperty; } public string OtherProperty { get; private set; } public string OtherPropertyDisplayName { get; internal set; } public override string FormatErrorMessage(string name) { return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, OtherPropertyDisplayName ?? OtherProperty); } public override bool RequiresValidationContext { get { return true; } } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { PropertyInfo otherPropertyInfo = validationContext.ObjectType.GetProperty(OtherProperty); if (otherPropertyInfo == null) { return new ValidationResult(String.Format(CultureInfo.CurrentCulture, DataAnnotationsResources.CompareAttribute_UnknownProperty, OtherProperty)); } object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null); if (!Equals(value, otherPropertyValue)) { if (OtherPropertyDisplayName == null) { OtherPropertyDisplayName = GetDisplayNameForProperty(validationContext.ObjectType, OtherProperty); } return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } return null; } private static string GetDisplayNameForProperty(Type containerType, string propertyName) { ICustomTypeDescriptor typeDescriptor = GetTypeDescriptor(containerType); PropertyDescriptor property = typeDescriptor.GetProperties().Find(propertyName, true); if (property == null) { throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, DataAnnotationsResources.Common_PropertyNotFound, containerType.FullName, propertyName)); } IEnumerable attributes = property.Attributes.Cast(); DisplayAttribute display = attributes.OfType().FirstOrDefault(); if (display != null) { return display.GetName(); } DisplayNameAttribute displayName = attributes.OfType().FirstOrDefault(); if (displayName != null) { return displayName.DisplayName; } return propertyName; } private static ICustomTypeDescriptor GetTypeDescriptor(Type type) { return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type); } } }