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

时间:2018-02-28 22:58:27

标签: c# asp.net asp.net-mvc unobtrusive-validation

我正在尝试为MVC 6实现自定义jQuery Unobtrusive Validation属性。下面是一个属性的 2018-02-28 16:57:17.117+0000 INFO ======== Neo4j 3.2.9 ======== 2018-02-28 16:57:17.188+0000 INFO Starting... 2018-02-28 16:57:18.629+0000 INFO Write transactions to database disabled 2018-02-28 16:57:19.054+0000 INFO Bolt enabled on 127.0.0.1:7687. 2018-02-28 16:57:19.084+0000 INFO Initiating metrics... 2018-02-28 16:57:20.539+0000 INFO Attempting to join cluster of [10.2.48.87:5001, 10.2.48.88:5001, 10.2.48.89:5001] 2018-02-28 16:57:50.665+0000 ERROR Failed to start Neo4j: Starting Neo4j failed: Component 'org.neo4j.server.database.LifecycleManagingDatabase@52405ea8' was successfully initialized, but failed to start. Please see the attached cause exception "Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}}". Starting Neo4j failed: Component 'org.neo4j.server.database.LifecycleManagingDatabase@52405ea8' was successfully initialized, but failed to start. Please see the attached cause exception "Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}}". org.neo4j.server.ServerStartupException: Starting Neo4j failed: Component 'org.neo4j.server.database.LifecycleManagingDatabase@52405ea8' was successfully initialized, but failed to start. Please see the attached cause exception "Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}}". at org.neo4j.server.exception.ServerStartupErrors.translateToServerStartupError(ServerStartupErrors.java:68) at org.neo4j.server.AbstractNeoServer.start(AbstractNeoServer.java:215) at org.neo4j.server.ServerBootstrapper.start(ServerBootstrapper.java:107) at org.neo4j.server.ServerBootstrapper.start(ServerBootstrapper.java:80) at org.neo4j.server.enterprise.EnterpriseEntryPoint.main(EnterpriseEntryPoint.java:32) Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.server.database.LifecycleManagingDatabase@52405ea8' was successfully initialized, but failed to start. Please see the attached cause exception "Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}}". at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:444) at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107) at org.neo4j.server.AbstractNeoServer.start(AbstractNeoServer.java:207) ... 3 more Caused by: java.lang.RuntimeException: Error starting org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory, /opt/neo4j-enterprise-3.2.9/data/databases/graph.db at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.initFacade(GraphDatabaseFacadeFactory.java:209) at org.neo4j.kernel.ha.HighlyAvailableGraphDatabase.<init>(HighlyAvailableGraphDatabase.java:50) at org.neo4j.server.enterprise.EnterpriseNeoServer.lambda$static$0(EnterpriseNeoServer.java:68) at org.neo4j.server.database.LifecycleManagingDatabase.start(LifecycleManagingDatabase.java:89) at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:434) ... 5 more Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.cluster.client.ClusterJoin@5210d51b' was successfully initialized, but failed to start. Please see the attached cause exception "Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}}". at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:444) at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107) at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:434) at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107) at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.initFacade(GraphDatabaseFacadeFactory.java:205) ... 9 more Caused by: java.util.concurrent.TimeoutException: Conversation-response mapping: {1/13#=ResponseFuture{conversationId='1/13#', initiatedByMessageType=join, response=null}} at org.neo4j.cluster.statemachine.StateMachineProxyFactory$ResponseFuture.get(StateMachineProxyFactory.java:315) at org.neo4j.cluster.client.ClusterJoin.joinByConfig(ClusterJoin.java:143) at org.neo4j.cluster.client.ClusterJoin.start(ClusterJoin.java:82) at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:434) ... 13 more 2018-02-28 16:57:50.666+0000 INFO Neo4j Server shutdown initiated by request 实现,它查看类中的相邻属性并将其与编译时常量进行比较。 / p>

IsValid()

在大多数情况下,这完全符合预期。我遇到的唯一问题是引用的属性及其值是Enum的衍生物(例如,让我们假设我们的枚举是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也是相同的。

我认为这与拳击有关,但无法精确定位。提前谢谢。

1 个答案:

答案 0 :(得分: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
}

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

但是,当值向下转换为object时,object == object运算符会执行Object.ReferenceEquals()检查。因为枚举是价值类型,所以它们必须得到&#34;盒装&#34;转换为新对象以便转换为objects,并且这些新对象将存在于不同的内存位置。因此,ReferenceEquals()将是错误的。

相反,请使用object.Equals()方法,该方法会传递给各个班级.Equals()覆盖。在这种情况下,枚举类型覆盖.Equals()将检查该值是否可以转换为Result,以及结果值是否与this一个相同&# 39; S

object.Equals(value1, value2)优于value1.Equals(value2)的优点是,如果value1为空,则不会获得空例外。