2010-12-13 2 views
3

사전의 키로 식> 식을 어떻게 사용할 수 있습니까?식 <Func<object>>을 사전의 키로 사용

방금 ​​Expression 인스턴스로 게임을 시작했으며 원하는 작업을 수행 할 수 있는지 확실하지 않습니다.

두 개의 동일한식이 같지 않은 것 같습니다. 식을 키로 사용하여 사전에 항목을 넣을 수는 있지만 키가 포함되어 있는지 사전에 물어 보면 거짓을 반환합니다. 매우 동일한 표현식 인스턴스.

TypeToTest test = new TypeToTest(); 
Expression<Func<object>> expression =()=>test.PropertyA; 
IDictionary<Expression<Func<object>>,bool> dictionary = new Dictionary<Expression<Func<object>>, bool>(); 
dictionary[expression] = true; 
Assert.That (dictionary.ContainsKey(expression), Is.True); 
Assert.That (dictionary.ContainsKey(()=>test.PropertyA), Is.True); 

위의 마지막 줄이 실패하면 성공할 수 있습니다.

의도는 개체의 속성이나 메서드에 적용되는 규칙 집합을 정의 할 수 있으므로 예를 들어 속성을 편집 할 수 있는지 또는 사전의 특정 키가있는 값 삭제할 수 있습니다. 나는 그것이 편집 가능한지 (다른 속성에 따라 편집이 다를 수 있기 때문에) 편집 가능한 객체에 플래그를 갖고 싶지 않습니다. 그리고 삭제 가능한지 여부를 결정하는 또 다른 클래스는 관련 규칙을 유지 관리하는 책임이있는 또 다른 클래스입니다. 객체가 앞으로 확장 될 때 객체의 구성 부분의 편집 가능성/액세스 가능성/삭제 가능성을 설명하기 위해 더 많은 규칙이 추가 될 수 있습니다. 그 말이 맞는다면.

here 비슷한 게시물이 있었지만 이것이 속성 이름을 기반으로하는 것으로 보입니다. 메서드 및 인수를 키로 지정할 수 있기를 바랍니다. 따라서 객체의 editablity를 결정할 수 있습니다. 키에 기초한 사전에서.

이와 비슷한 것이 가능하거나 하늘에 파이가 있습니까?

답변

4

다른 참조를 비교할 때 예상되는 동작입니다.이 유형은 Equals을 무시하지 않으며 IEquatable<T>을 구현하지 않습니다. 사용자 정의 비교자를 작성하고 (아마도 간단히 ToString()을 비교) 사전에 전달합니다. 그러나 IMO Expression은 좋은 선택이 아닙니다.

다음은 이며 반드시 ToString()을 통한 강력한 사용은 아닙니다; 자신의 재량에 따라 사용하십시오 Expression 유형의

class Program { 
    static void Main() { 
     TypeToTest test = new TypeToTest(); 
     Expression<Func<object>> expression =() => test.PropertyA; 
     IDictionary<Expression<Func<object>>, bool> dictionary = 
      new Dictionary<Expression<Func<object>>, bool>(
       new ToStringComparer<Expression<Func<object>>>()); 
     dictionary[expression] = true; 

     bool x = dictionary.ContainsKey(expression), // true 
      y = dictionary.ContainsKey(() => test.PropertyA); // true 
    } 
} 
class ToStringComparer<T> : IEqualityComparer<T> where T : class { 
    public bool Equals(T x, T y) { 
     if ((x == null && y == null) || ReferenceEquals(x,y)) return true; 
     if (x == null || y == null) return false; 
     return x.ToString() == y.ToString(); 
    } 
    public int GetHashCode(T obj) { 
     return obj == null ? 0 : obj.ToString().GetHashCode(); 
    } 
} 
+0

왜 키의 좋은 선택이 아니라고 생각합니까? 잘 정의 된 동등성 검사가 없기 때문에 유형이 확장되면 (다른 인터페이스라고 말하면) –

+0

@Sam - 각 속성/메소드가 개별적으로 제어되는 방식으로 개별적으로 제어되도록하는 것으로 보입니다. 예를 들어; 'x => x.A'는'y => y.A'와 같은 표현식입니까? 표현식이 캡처 된 변수 래퍼 인 객체 인스턴스를 캡처하면 어떻게 될까요? 이것에 대한 –

+0

멋진 솔루션입니다. – IamStalker

2

서브 클래스는 그 어려운 등의 사전 키를 사용하여 만드는 EqualsGetHashCode 방법을 대체하지 않습니다. 귀하의 사전은 참조 동등성을 사용하고 두 번 발생하면 ()=>test.PropertyA은 두 개의 서로 다른 표현 트리 객체를 생성합니다.

자신 만의 IEqualityComparer<Expression> 구현을 작성하여 사전 생성자에 전달할 수 있습니다. 비교 자에서 각각 Expression 클래스를 처리하고 해당 속성을 비교하는 EqualsGetHashCode 메서드를 작성합니다.

+0

'Expression'은'GetHashCode'를 오버라이드하므로'IEqualityComparer '구현은 구현을 위임 할 수 있습니다 (동일한 인스턴스가 동일한 해시 코드를 제공하는지 확인). – Richard

관련 문제