سؤال

لدي مشكلة حيث أريد أن تقارن المجالات (على سبيل المثال ، وضمان بدء وقت قبل انتهاء الوقت).أنا باستخدام System.ComponentModel.DataAnnotations سمات أجل التحقق من الصحة.

فكرتي الأولى كانت شيئا من هذا القبيل:

public enum CompareToOperation
{
    EqualTo,
    LessThan,
    GreaterThan
}

public class CompareToAttribute : ValidationAttribute
{
    CompareToOperation _Operation;
    IComparable _Comparision;

    public CompareToAttribute(CompareToOperation operation, Func<IComparable> comparison)
    {
       _Operation = operation;
       _Comparision = comparison();
    }

    public override bool IsValid(object value)
    {
    if (!(value is IComparable))
        return false;

    switch (_Operation)
    {
        case CompareToOperation.EqualTo: return _Comparision.Equals(value);
        case CompareToOperation.GreaterThan: return _Comparision.CompareTo(value) == 1;
        case CompareToOperation.LessThan: return _Comparision.CompareTo(value) == -1;
    }

    return false;
    }
}

public class SimpleClass
{
   public DateTime Start {get;set;}
   [CompareTo(CompareToOperation.GreaterThan, () => this.Start)] // error here
   public DateTime End {get;set;}
}

هذا لا يعمل ومع ذلك ، هناك خطأ التحويل حيث سمة ملحوظة:

Expression cannot contain anonymous methods or lambda expressions

لا أحد يملك الحل لهذا ؟ أو نهج مختلف عن التحقق من صحة حقل واحد مقارنة مع قيمة أخرى ؟

هل كانت مفيدة؟

المحلول

A جدا الطريقة البشعة التي لا يكاد مرن يتم وضعه على الطبقة واستخدام التفكير.لم يتم اختبار هذا, لذلك أنا لست متأكدا من أنها تعمل ، ولكنه ترجمة :)

public enum CompareToOperation
{
    EqualTo,
    LessThan,
    GreaterThan
}

public class CompareToAttribute : ValidationAttribute
{
    CompareToOperation _Operation;
    string _ComparisionPropertyName1;
    string _ComparisionPropertyName2;

    public CompareToAttribute(CompareToOperation operation, string comparisonPropertyName1, string comparisonPropertyName2)
    {
        _Operation = operation;
        _ComparisionPropertyName1 = comparisonPropertyName1;
        _ComparisionPropertyName2 = comparisonPropertyName2;
    }

    private static IComparable GetComparablePropertyValue(object obj, string propertyName)
    {
        if (obj == null) return null;
        var type = obj.GetType();
        var propertyInfo = type.GetProperty(propertyName);
        if (propertyInfo == null) return null;
        return propertyInfo.GetValue(obj, null) as IComparable;
    }

    public override bool IsValid(object value)
    {
        var comp1 = GetComparablePropertyValue(value, _ComparisionPropertyName1);
        var comp2 = GetComparablePropertyValue(value, _ComparisionPropertyName2);

        if (comp1 == null && comp2 == null)
            return true;

        if (comp1 == null || comp2 == null)
            return false;

        var result = comp1.CompareTo(comp2);

        switch (_Operation)
        {
            case CompareToOperation.LessThan: return result == -1;
            case CompareToOperation.EqualTo: return result == 0;
            case CompareToOperation.GreaterThan: return result == 1;
            default: return false;
        }
    }
}

[CompareTo(CompareToOperation.LessThan, "Start", "End")]
public class SimpleClass
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

نصائح أخرى

وفحصت AccountMOdel في المشروع الافتراضي MVC2، وهناك سمة PropertiesMustMatchAttribute تطبيقها على ChangePasswordModel للتحقق من صحة أن NewPassword وConfirmPassword المباراة

   [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute
{
    private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";

    private readonly object _typeId = new object();

    public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
        : base(_defaultErrorMessage)
    {
        OriginalProperty = originalProperty;
        ConfirmProperty = confirmProperty;
    }

    public string ConfirmProperty
    {
        get;
        private set;
    }

    public string OriginalProperty
    {
        get;
        private set;
    }

    public override object TypeId
    {
        get
        {
            return _typeId;
        }
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
            OriginalProperty, ConfirmProperty);
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
        object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
        object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
        return Object.Equals(originalValue, confirmValue);
    }
}

ومن نظرة منه، لا يمكن القيام بذلك.

يتم تطبيق

وValidationAttribute على الممتلكات وعلى هذا النحو يقتصر على تلك الممتلكات فقط.

وأفترض أن المسألة ليست واحدة مجردة ولديك مشكلة حقيقية تتطلب وجود مثل هذه المصادقة. ربما انها النص تكرار كلمة السر؟ : -)

في أي حال، كمحاولة للتغلب على هذه المشكلة لديك تحتاج إلى الاعتماد على السياق الذي تعمل فيه. نماذج ويب ASP.NET فعل ذلك مع ControlToCompare ولأن كل شيء هو السيطرة وعلينا تسمية الحاويات في مكان انها الى حد ما من السهل معرفة الأمور على أساس سلسلة بسيطة.

في ASP.NET MVC يمكنك نظريا أن تفعل الشيء نفسه، ولكن! سوف العميل يكون من السهل إلى حد ما والطبيعية - مجرد استخدام #PropertyName والقيام الاشياء الخاصة بك في جافا سكريبت. جانب الخادم على الرغم من أن تحتاج إلى الوصول إلى شيء خارجي إلى الدرجة السمة الخاصة بك - الكائن طلب - وهذا هو لا لا بقدر ما انا قلق

.

وجميع في كل شيء، هناك دائما سبب للأشياء (لا) يحدث و، في رأيي، وهو السبب في مايكروسوفت لم تنفذ هذا النوع من المصادقة في المقام الأول هو - أنه ليس ممكنا من دون الأشياء المذكورة أعلاه.

ولكن! وأنا آمل حقا أن أكون مخطئا. I DO تحتاج إلى مقارنة التحقق من صحة لتكون سهلة الاستخدام ...

وأعتقد أنك تحتاج إلى شيء من هذا القبيل:

public class EqualsAttribute : ValidationAttribute
{
 private readonly String _To;

 public EqualsAttribute(String to)
 {
  if (String.IsNullOrEmpty(to))
  {
   throw new ArgumentNullException("to");
  }
  if (String.IsNullOrEmpty(key))
  {
   throw new ArgumentNullException("key");
  }
  _To = to;
 }


 protected override Boolean IsValid(Object value, ValidationContext validationContext, out ValidationResult validationResult)
 {
  validationResult = null;
  var isValid = IsValid(value, validationContext);
  if (!isValid)
  {
   validationResult = new ValidationResult(
    FormatErrorMessage(validationContext.DisplayName),
    new [] { validationContext.MemberName });
  }
  return isValid;
 }

 private Boolean IsValid(Object value, ValidationContext validationContext)
 {
  var propertyInfo = validationContext.ObjectType.GetProperty(_To);
  if (propertyInfo == null)
  {
   return false;
  }
  var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);
  return Equals(value, propertyValue);
 }

 public override Boolean IsValid(Object value)
 {
  throw new NotSupportedException();
 }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top