2014-02-11 2 views
0

EventHandler를 ConditionalWeakTable에 키로 저장하려고했지만 값에 액세스하려고 시도했지만 찾을 수 없습니다.EventHandler를 Key로 사용하는 조건부 대기 테이블

var eventReceiver = new StateChangedEventReceiver(); 

var dict = new ConditionalWeakTable<EventHandler<EventArgs>, string>(); 
dict.Add(eventReceiver.OnStateChanged, "Foobar"); 

string dummy; 
dict.TryGetValue(eventReceiver.OnStateChanged, out dummy); // returns false!!! 

StateChangedEventReceiver의 코드는 다음과 같습니다

public class StateChangedEventReceiver 
{ 
    public void OnStateChanged(object sender, EventArgs args) 
    { 
    } 
} 

가 나는 사전 예상대로 작동을 사용하여 동일한 동작을 테스트 :

var eventReceiver = new StateChangedEventReceiver(); 

var dict = new Dictionary<EventHandler<EventArgs>, string>(); 
dict.Add(eventReceiver.OnStateChanged, "Foobar"); 

string dummy; 
dict.TryGetValue(eventReceiver.OnStateChanged, out dummy); // returns true -> as expected 

이유는 무엇입니까?

비교자를 취하는 ConditionalWeakTable의 생성자가 없습니다. WeakEventManager-Class에서 .Net 4.5로 .Net 4.0으로 "포트"(나는 소스 코드가 없음)를 사용하려고하므로 .NET 4.0으로 업데이트 할 수 없습니다. 내가 올바르게 작동하지만 모든 이벤트 처리기를 제거 할 수 없습니다.

답변

1

eventReceiver.OnStateChanged라고 말하면 해당 표현식을 EventHandler<EventArgs>으로 변환하면 매번 새로운 대리인 인스턴스가 생성됩니다. 메서드 자체에는 연결된 단일 대리자가 없습니다. 임의적으로 동일한 메소드에 바인드 된 많은 위임자를 가질 수 있습니다.

ConditionalWeakTable 클래스는 해당 키에 대해 참조 평등을 사용하는 것처럼 보입니다. 기본 internal struct DependentHandle 시설이 공개되어 있지 않기 때문에 다른 의미론을 사용하여 사용자 지정 ConditionalWeakTable을 구축하는 것은 불가능합니다.

해결 방법 항상 동일한 위임 인스턴스를 전달하십시오.

+0

WeakEventManager의 공용 인터페이스가 EventHandler-instance를 사용하고 매번 같은 인스턴스를 전달할 수 없기 때문에 동일한 위임 인스턴스를 ConditionalWeakTable에 추가 할 수 없습니다. 어쩌면 고유 한 대리자와 함께 등록 된 모든 이벤트 처리기를 기억할 수 있습니다 (키/값을 가비지 수집 할 수 없기 때문에 사전에 저장하는 것이 효과가 없습니다). –

+0

나는 당신의 생각을 증명하고 당신 말이 맞습니다. 대리자에 메서드를 할당하면 새 delegate-instance가 만들어지는 것을 보았습니다. 문제는 매번 같은 인스턴스를 전달할 수 없다는 것입니다. –

+0

두 가지 아이디어가 있습니다 : 당신이 보았던 모든 이벤트 핸들러 (오브젝트 수명에 영향을 미치지 않는 약한 참조를 사용하는 것)를 기억하거나 리플렉션을 사용하여'ConditionalWeakTable'과'DependentHandle'을 열어서 커스텀'ConditionalWeakTable'을 빌드하십시오. 이 코드가 프레임 워크의 다음 주요 버전을 깨뜨릴 것으로 기대하십시오. 당신은'ConditionalWeakTable'의 소스 코드로 시작하여'DependentHandle'에 대한 개인 호출 만하면됩니다. – usr

관련 문제