2009-04-08 3 views
3

엔티티와 집계 루트를 비교할 때 Oren Eini에서 빌린 ABC를 사용합니다 : Generic Entity Equality. 가치 사물을 위해 나는 똑같이 독창적이었다. 지미 Bogard의 가치 개체 ABC 사용 : Generic Value Object Equality구성 vs 등가 및 해시 코드 공급자에 대한 상속

내 질문은; 이러한 ABC를 상속받는 것이 좋을까요? 아니면 일반 equality/comparer을 사용하고 앞서 언급 한 동작을 대신 작성해야합니까? 나는 위의 평등 구현을 재사용하려고한다.

이것이 System.Object의 기본 같음 구현으로 인해 언어 피의 사용이 편리하지만 재미있는 문제를 제공한다고 생각합니다. Jon Skeet은 여기에 자세히 설명되어 있습니다. Comparison methods

누구나 프로 또는 단점을 생각할 수 있습니까? 상식을 상속

  • 쉽게하고 는 상자에서 연산자 오버로드를 제공합니다.
  • 2 개의 추상 "드래그"해야합니까? 클래스가 너무 많습니까? 그것 내 상속 그래프 더 복잡하게/ 커플 링을 추가합니다.
  • DI를 사용하여 제공자를 구성 할 수 있습니까?

따라서 요약하면 엔터티에 대한 사용자 지정 같음 구현을 사용한 경험이있는 사람이 있습니까? 내 목표는 구현 선택에 대한 전반적인 이해를 돕고 솔루션의 구현을 통해 프로젝트의 수명을 연장하고 (엔트로피를 줄임) 유지 보수성을 향상시키는 것입니다.

답변

0

이 질문에 정말 답변하지는 않지만 (미안 해요!), 여기에있는 질문에 도움을주기위한 프로젝트라고 생각합니다. 나는이 물건을 조금 뒤로 썼다. 그러나 그 이후로 아무것도하지 않고 있었다.

프로젝트는 Essence (http://essence.codeplex.com/)라고하며, System.Linq.Expression 라이브러리를 사용하여 특성을 기반으로 Equals/GetHashCode/CompareTo/ToString의 표준 표현을 생성하고 IEqualityComparer를 만들 수 있습니다. IComparer 클래스는 인수 목록을 기반으로합니다. (나는 또한 더 많은 아이디어가 있지만 너무 많은 것을 계속하기 전에 커뮤니티 의견을 얻고 싶다.)

(이것이 의미하는 바는 손으로 쓰는 것보다 거의 빠르다는 것이다. CompareTo(); Linq.Expressions 3.5 릴리스에서 변수의 개념을 가지고 있지 않습니다 - 그래서 당신이 CompareTo() 일치하는 얻을 때 두 번 기본 개체에 대한 호출해야합니다 .DLR 확장을 사용하여 Linq.Expressions은 이것을 해결합니다. 나는 emit il을 사용할 수 있다고 생각하지만 당시에는 영감을 얻지 못했습니다.)

이것은 꽤 간단한 생각이지만, 전에는 그것을 보지 못했습니다.

이제 코드 일을 잃어 버렸습니다 (코드 조각에 대한 기사 작성, 일부 코드 문서화 등 포함).하지만 느낀다면 그렇게 할 수 있습니다. 그것은 관심의 대상이 될 것입니다.

(코드 플렉스 사이트에는 다운로드 가능한 패키지가 없으므로 원본에 가서 원하는 코드 인 f # (모든 테스트 코드가 C#이지만)로 작성되었습니다. 배우기.)

어쨌든, 여기에 내 테스트 사례의 일부 샘플 C# 예제가 있습니다.

// -------------------------------------------------------------------- 
    // USING MY ESSENCE LIBRARY: 
    // -------------------------------------------------------------------- 
    [EssenceClass(UseIn = EssenceFunctions.All)] 
    public class TestEssence : IEquatable<TestEssence>, IComparable<TestEssence> 
    { 
     [Essence(Order=0, Format="i={0},")]   public int MyInt   { get; set; } 
     [Essence(Order=1, Format="s={0},")]   public string MyString  { get; set; } 
     [Essence(Order=2, Format="d={0:yyyy-MM-dd}")] public DateTime MyDateTime { get; set; } 

     public override int GetHashCode()        { return Essence<TestEssence>.GetHashCodeStatic(this); } 
     public override string ToString()        { return Essence<TestEssence>.ToStringStatic(this); } 
     public int CompareTo(TestEssence other)       { return Essence<TestEssence>.CompareToStatic(this, other); } 

     public static bool operator ==(TestEssence lhs, TestEssence rhs) { return Essence<TestEssence>.EqualsStatic(lhs, rhs); } 
     public override bool Equals(object obj)       { return this == (TestEssence)obj; } 
     public bool Equals(TestEssence other)       { return this == other; } 
     public static bool operator !=(TestEssence lhs, TestEssence rhs) { return !(lhs == rhs); } 
    } 

    // -------------------------------------------------------------------- 
    // EQUIVALENT HAND WRITTEN CODE: 
    // -------------------------------------------------------------------- 
    public class TestManual 
    { 
     public int MyInt; 
     public string MyString; 
     public DateTime MyDateTime; 

     public override int GetHashCode() 
     { 
      var x = MyInt.GetHashCode(); 
      x *= Essence<TestEssence>.HashCodeMultiplier; 
      x ^= (MyString == null) ? 0 : MyString.GetHashCode(); 
      x *= Essence<TestEssence>.HashCodeMultiplier; 
      x ^= MyDateTime.GetHashCode(); 
      return x; 
     } 

     public static bool operator ==(TestManual lhs, TestManual rhs) 
     { 
      if (ReferenceEquals(lhs, null)) 
      { 
       if (ReferenceEquals(rhs, null)) 
        return true; 
       return false; 
      } 
      if (ReferenceEquals(rhs, null)) 
       return false; 
      if (ReferenceEquals(lhs, rhs)) 
       return true; 
      if (typeof(TestManual) != rhs.GetType()) 
       return false; 

      return lhs.MyInt == rhs.MyInt 
       && lhs.MyString == rhs.MyString 
       && lhs.MyDateTime == rhs.MyDateTime; 
     } 

     public override bool Equals(object obj)     { return this == obj as TestManual; } 
     public bool Equals(TestManual other)     { return this == other; } 
     public static bool operator !=(TestManual lhs, TestManual rhs) { return !(lhs == rhs); } 

     public override string ToString() 
     { 
      if (MyString == null) 
       return string.Format("i={0},d={1:yyyy-MM-dd}", MyInt, MyDateTime); 

      return string.Format("i={0},s={1},d={2:yyyy-MM-dd}", MyInt, MyString, MyDateTime); 
     } 

     public int CompareTo(TestManual other) 
     { 
      if (other == null) 
       return 1; 
      if (ReferenceEquals(this, other)) 
       return 0; 

      int result = 0; 

      result = MyInt.CompareTo(other.MyInt); 
      if (result != 0) return result; 
      result = MyString.CompareTo(other.MyString); 
      if (result != 0) return result; 
      result = MyDateTime.CompareTo(other.MyDateTime); 
      if (result != 0) return result; 

      return result; 
     } 
    } 

    // -------------------------------------------------------------------- 
    // -------------------------------------------------------------------- 
    // ALTERNATIVE USAGE 
    // -------------------------------------------------------------------- 
    // -------------------------------------------------------------------- 

    class Simple 
    { 
     public Simple(int value) { Value1 = value; } 
     public Simple(int value1, int value2) { Value1 = value1; Value2 = value2; } 
     public readonly int Value1; 
     public readonly int Value2; 
    } 

    [Test] 
    public void TestReverseForwardString() 
    { 
     var _11 = new Simple(1, 1); 
     var _12 = new Simple(1, 2); 
     var _21 = new Simple(2, 1); 
     var _22 = new Simple(2, 2); 

     var items = new[] { _11, _12, _21, _22 }; 
     var reverseComparer = Essence<Simple>.CreateComparer("-Value1", "Value2"); 

     Array.Sort(items, reverseComparer); 

     Assert.AreSame(_21, items[0]); 
     Assert.AreSame(_22, items[1]); 
     Assert.AreSame(_11, items[2]); 
     Assert.AreSame(_12, items[3]); 
    } 

    [Test] 
    public void TestReverseForwardLambda() 
    { 
     var _11 = new Simple(1, 1); 
     var _12 = new Simple(1, 2); 
     var _21 = new Simple(2, 1); 
     var _22 = new Simple(2, 2); 

     var items = new[] { _11, _12, _21, _22 }; 
     var reverseComparer = Essence<Simple>.CreateComparer(x => x.Action.ReverseNext, x => x.Member.Value1, x => x.Member.Value2); 

     Array.Sort(items, reverseComparer); 

     Assert.AreSame(_21, items[0]); 
     Assert.AreSame(_22, items[1]); 
     Assert.AreSame(_11, items[2]); 
     Assert.AreSame(_12, items[3]); 
    } 

재미있게 보내십시오!

폴.

+1

대답하지 않습니다. 그럼에도 불구하고 재미있는 독서. 감사. –