我正在尝试为MVC 6实现自定义jQuery Unobtrusive Validation属性。以下是该属性的IsValid()
实现,该实现查看类中的相邻属性并将其与编译时常量进行比较。
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult result = ValidationResult.Success;
// Simplest case, there is something in this field
if (!string.IsNullOrEmpty(value?.ToString()))
return result;
// Check relative field
try
{
// Grab the property referenced via reflection
var relativeProperty = validationContext.ObjectType.GetProperty(this._relativePropertyName);
// Compare the runtime value of that property to the Attribute initialized value
if (relativeProperty.GetValue(validationContext.ObjectInstance) == this._relativeValue)
{
// Fail if those 2 values are equal
result = new ValidationResult(this.ErrorMessageString);
}
}
catch (Exception)
{
result = new ValidationResult(this.ErrorMessageString);
}
return result;
}
在大多数情况下,这完全符合预期。我唯一遇到的问题是所引用的属性及其值是枚举的派生类(例如,让我们假设我们的枚举为
Result
)。在一个类中,实现此属性的外观如下:public class TestObject
{
public Result TestResult { get; set; }
[IsEqual(nameof(TestResult), Result.Pass)]
public string PassComment { get; set; }
}
当调试器到达
if(relativeProperty.GetValue(validationContext.ObjectInstance) == this._relativeValue)
行时,即使relativeProperty.GetValue(validationContext.ObjectInstance)
解析为Result.Pass
,它也会失败。使用立即窗口,relativeProperty.GetValue(validationContext.ObjectInstance)
= Result.Pass
以及this._relativeValue
= Result.Pass
小旁注,在两个值上调用
.GetType()
也是相等的。我假设这与拳击有关,但无法查明。提前致谢。
最佳答案
不要使用==
来评估非强类型输入的相等性。考虑以下:
void Main()
{
Console.WriteLine(((object)Result.Pass) == (object)Result.Pass);
// False
Console.WriteLine(((object)Result.Pass).Equals((object)Result.Pass));
// True
Console.WriteLine(object.Equals((object)Result.Pass,(object)Result.Pass));
// True
}
public enum Result{
Pass, Fail
}
在C#中,当比较某些类型的对象时,可以重写
==
运算符以简化语法,如果尝试对两个不兼容的类型进行==
运算,则具有提供编译时错误的优点。有些人认为它看起来更好。但是,当将值向下转换为
object
时,object == object
运算符将执行Object.ReferenceEquals()
检查。由于枚举是值类型,因此必须将它们“装箱”到新对象中才能转换为objects
,并且这些新对象将存在于不同的内存位置。因此,ReferenceEquals()
将为false。而是使用
object.Equals()
方法,该方法传递给各个类的.Equals()
替代。在这种情况下,Enum类型的.Equals()
覆盖将检查该值是否可以强制转换为Result
,以及结果值是否与this
相同。与
object.Equals(value1, value2)
相比,value1.Equals(value2)
的优势在于,如果value1
为null,则不会出现null异常。