当通过反射检索到值时,枚举失败==

jef*_*237 1 c# asp.net asp.net-mvc unobtrusive-validation

我正在尝试为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;
}
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,这完全符合预期.我遇到的唯一问题是引用的属性及其值是Enum的衍生物(例如,让我们假装我们的枚举是Result).实现此属性在类中如下所示:

public class TestObject
{
    public Result TestResult { get; set; }
    [IsEqual(nameof(TestResult), Result.Pass)]
    public string PassComment { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当调试器到达if(relativeProperty.GetValue(validationContext.ObjectInstance) == this._relativeValue)它失败的行时,即使relativeProperty.GetValue(validationContext.ObjectInstance)解析为Result.Pass.使用立即窗口,relativeProperty.GetValue(validationContext.ObjectInstance)= Result.Passthis._relativeValue=Result.Pass

小旁注,呼吁.GetType()两个值也是相等的.

我假设这与拳击有关,但无法确定它.提前致谢.

Str*_*ior 5

不要==用于评估非强类型事物的相等性.考虑以下:

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
}
Run Code Online (Sandbox Code Playgroud)

在C#中,==可以重写运算符,以便在比较某些类型的对象时使语法更容易,如果您尝试使用==两种不兼容的类型,则可以提供编译时错误.有些人认为它看起来更好.

但是,当值向下转换为objects时,object == object操作员执行Object.ReferenceEquals()检查.由于枚举是值类型,因此必须将它们"装箱"到新对象中才能进行转换objects,并且这些新对象将存在于不同的内存位置.因此,ReferenceEquals()将是错误的.

相反,使用该object.Equals()方法,该方法传递给单个类的.Equals()覆盖.在这种情况下,Enum类型的覆盖.Equals()将检查值是否可以转换为a Result,以及结果值是否与thisone 相同.

以优势object.Equals(value1, value2)value1.Equals(value2)的是,如果你没有得到一个空的例外value1是空的.