编写CompareTo DataAnnotation属性 [英] Writing a CompareTo DataAnnotation Attribute
问题描述
我遇到一种情况需要与字段进行比较(例如,确保开始时间早于结束时间)。我正在使用 System.ComponentModel.DataAnnotations
属性进行验证。
I have a situation where I want to compare to fields (example, ensuring the start time is before the end time). I'm using the System.ComponentModel.DataAnnotations
attributes for my validation.
我的第一个想法是这样的:
My first thought was something like this:
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;}
}
但是这不起作用,在编译器错误中标记了属性:
This doesn't work however, there's a compiler error where the attribute is marked:
Expression cannot contain anonymous methods or lambda expressions
有人对此有解决方案吗?还是与另一字段的值相比,用于验证一个字段的另一种方法?
Does anyone have a solution for this? Or a different approach for validating one field compared to the value of another?
推荐答案
一个非常丑陋不那么灵活的方法是将其放在类上并使用反射。我还没有测试过,所以我实际上不确定它是否可以工作,但是它确实可以编译:)
A very ugly way that's not nearly as flexible is to put it on the class and use reflection. I haven't tested this, so I'm not actually sure it works, but it does compile :)
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; }
}
这篇关于编写CompareTo DataAnnotation属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!