2014-02-12 59 views
0

我有很多類與往往很多屬性/字段primitive typesarray/nullable原始類型。有沒有一種快速有效的方法讓班級公平?

Public Class ClassN 
    Public P1 As Integer 
    Public P2 As Byte() 
    Public P3 As String 
    Public P4 As Short? 
    '... 
    Public P17 As Boolean 
    Public P18 As Char() 
End Class 

在這一點上,我想出了使用attributes的解決方案和一個「平等服務類」的執行相等測試。但是有沒有更快,更高效的方法來實現呢?

背後

<AttributeUsage((AttributeTargets.Field Or AttributeTargets.Property), AllowMultiple:=False, Inherited:=False)> _ 
Public Class EquatableAttribute 
    Inherits Attribute 
End Class 

Public Class ClassN 
    Implements IEquatable(Of ClassN) 

    <Equatable()> Public P1 As Integer 
    <Equatable()> Public P2 As Byte() 
    <Equatable()> Public P3 As String 
    <Equatable()> Public P4 As Short? 
    '... 
    <Equatable()> Public P17 As Boolean 
    <Equatable()> Public P18 As Char() 

    Public Overrides Function Equals(obj As Object) As Boolean 
     Return Me.Equals(TryCast(obj, ClassN)) 
    End Function 

    Public Overloads Function Equals(obj As ClassN) As Boolean Implements System.IEquatable(Of ClassN).Equals 
     Return EqualityServices.Equals(Of ClassN)(Me, obj) 
    End Function 

End Class 

Public NotInheritable Class EqualityServices 

    Private Sub New() 
    End Sub 

    Public Overloads Shared Function Equals(Of T)(obj1 As T, obj2 As T) As Boolean 
     If (obj1 Is Nothing) Then 
      Return obj2 Is Nothing 
     End If 
     If (obj2 Is Nothing) Then 
      Return False 
     End If 
     Dim type As Type = GetType(T) 
     Dim members As MemberInfo() = Nothing 
     If (Not EqualityServices.EquatableAttributeCache.TryGetValue(type, members)) Then 
      members = New MemberInfo(-1) {} 
      For Each info As MemberInfo In type.GetMembers((BindingFlags.Public Or BindingFlags.Instance)) 
       If (info.GetCustomAttributes(EqualityServices.EquatableAttributeType, False).Length > 0) Then 
        Select Case info.MemberType 
         Case MemberTypes.Field 
          Exit Select 
         Case MemberTypes.Property 
          With DirectCast(info, PropertyInfo) 
           If ((Not .CanRead) OrElse (.GetIndexParameters().Length > 0)) Then 
            Continue For 
           End If 
          End With 
          Exit Select 
         Case Else 
          Continue For 
        End Select 
        ReDim Preserve members(members.Length) 
        members(members.Length - 1) = info 
       End If 
      Next 
      EqualityServices.EquatableAttributeCache.Add(type, members) 
     End If 
     If (members.Length > 0) Then 
      Dim value1 As Object = Nothing 
      Dim value2 As Object = Nothing 
      For Each info As MemberInfo In members 
       Select Case info.MemberType 
        Case MemberTypes.Field 
         With DirectCast(info, FieldInfo) 
          type = .FieldType 
          value1 = .GetValue(obj1) 
          value2 = .GetValue(obj2) 
         End With 
         Exit Select 
        Case MemberTypes.Property 
         With DirectCast(info, PropertyInfo) 
          type = .PropertyType 
          value1 = .GetValue(obj1, Nothing) 
          value2 = .GetValue(obj2, Nothing) 
         End With 
         Exit Select 
        Case Else 
         Continue For 
       End Select 
       If (type.BaseType Is EqualityServices.ArrayType) Then 
        If (Not EqualityServices.SequenceEqual(CType(value1, Array), CType(value2, Array))) Then 
         Return False 
        End If 
       Else 
        If (Not Object.Equals(value1, value2)) Then 
         Return False 
        End If 
       End If 
      Next 
      Return True 
     End If 
     Return False 
    End Function 

    Private Shared Function SequenceEqual(ByVal array1 As Array, array2 As Array) As Boolean 
     If (array1 Is Nothing) Then 
      Return array2 Is Nothing 
     End If 
     If (array2 Is Nothing) Then 
      Return False 
     End If 
     If (array1.Rank <> array2.Rank) Then 
      Return False 
     End If 
     If (array1.Length <> array2.Length) Then 
      Return False 
     End If 
     Dim length As Integer = (array1.Length - 1) 
     If (length > -1) Then 
      Dim list1 As IList = CType(array1, IList) 
      Dim list2 As IList = CType(array2, IList) 
      For index = 0 To length 
       If (Not Object.Equals(list1.Item(index), list2.Item(index))) Then 
        Return False 
       End If 
      Next 
     End If 
     Return True 
    End Function 

    Private Shared ReadOnly EquatableAttributeCache As New Dictionary(Of Type, MemberInfo()) 
    Private Shared ReadOnly EquatableAttributeType As Type = GetType(EquatableAttribute) 
    Private Shared ReadOnly ArrayType As Type = GetType(Array) 

End Class 
+0

ReSharper的可生成相關的'Equals' ,'GetHashCode'等或您的'IEqualityComparer'代碼。你只需要ReSharper。 – sloth

+0

謝謝@DominicKexel,我會看看它。 –

+0

@DominicKexel由於沒有人回答我的問題,你可以總結你的評論作爲答案,我會接受嗎? –

回答

1

ReSharper代碼可以生成相關EqualsGetHashCode等,或爲你的IEqualityComparer代碼。

你剛好,需要ReSharper。

下面是一個例子(它的C#,因爲我只有在手的C ReSharper的排名-Edition):

enter image description here

enter image description here

enter image description here

相關問題