2017-04-18 11 views
1

Test2 및 Test3 잘 통과하는 동안 Test1 "System.ArgumentException : 메서드 인수 길이 불일치"문제가 발생합니다. 리플렉션을 사용하여 이벤트에 가입해야합니다. 간단한 방법을 사용하면 모든 것이 작동하지만, 람다에 들어가면 예상대로 작동하지 않습니다.메서드로 lambda Delegate.CreateDelegate "메서드 인수 길이 불일치"예외를 생성합니다.

디버깅은 모든 람다에 대해 "Void <> m__0 (Int32)"이며 올바른 이벤트 유형이며 "eventInfo.EventHandlerType"과 동일 함을 보여줍니다.

왜 실패합니까? 아니면 어떻게 해결할 수 있을까요?

Test1과 같이 λ로 생성 된 메서드에 인수를 더 추가합니까? 여기

:: 전체 코드 :

public class A 
{ 
    public void Test1() 
    { 
     var str = "aa"; 
     B.Subscribe(typeof(C), "myEvent", (int a) => { var any = str; }, null); 
    } 

    public void Test2() 
    { 
     B.Subscribe(typeof(C), "myEvent", (int a) => { var any = a; }, null); 
    } 

    public void Test3() 
    { 
     B.Subscribe<int>(typeof(C), "myEvent", callback, this); 
    } 

    public void callback(int a) { } 
} 

public static class B 
{ 
    public static void Subscribe<T>(Type type, string eventName, Action<T> callback, object target) 
    { 
     var eventInfo = type.GetEvent(eventName, BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static); 
     var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, target, callback.Method); 
     eventInfo.AddEventHandler(null, handler); 
    } 

} 

public sealed class C 
{ 
    public static event Action<int> myEvent; 
} 

편집 :

은 분명히 그것은 모노 버그입니다. Delegate를 얻는 GetInvocationList() [0]는 위의 예제에서 문제를 수정합니다.

이벤트를 구독하면 "System.InvalidCastException : 원본 형식에서 대상 형식으로 캐스트 할 수 없습니다."가 생성됩니다. 이벤트 유형의 행동하지만, 사용자 정의 위임이 아닌 경우는 다른 문제

public sealed class C 
{ 
    public static event MyDel myEvent; 
    public delegate void MyDel(int a); 
} 

가 (클래스 "C"가 그런 경우가 발생, 클래스 "C"가 위와 같이되어 있으면 패스)? 편집 # 2, 이벤트는 MyDel 유형을 예상하지만 Action Int32를 얻습니다. 어떤 유형의 이벤트가 있을지 모르기 때문에 Action<T>에서으로 MyDel 이상으로 변환하려면 어떻게해야합니까?

+1

MS .NET에서 올바르게 작동합니다. 모노 문제가 있습니까? – VinSmile

+0

모노 버그를 버그로 보입니다. 이것을 확인하십시오 http://lists.ximian.com/pipermail/mono-bugs/2010- December/126824.html –

+0

'MethodIn' 대신에'GetInvocationList()'(반환 된리스트의 첫 번째 요소)를 사용하면 어떻게 될까요? ? 후자는 작동해야하지만, @ VinSmile이 말했듯이, 아마 모노 문제 일 것입니다. –

답변

0

실제로 조사를 거친 후에 나는 target이 나빴던 것으로 나타났습니다.

클래스에 정의 된 메서드의 경우 대상 클래스 인스턴스는 괜찮습니다. lambdas의 경우 lambda의 경우 람다가 작성된 메서드 내부에서 정의 된 로컬 변수를 간섭하지 않는 한 null로 간주하고 적어도 NULL과 함께 사용합니다 ().

그래서 액션Delegate.CreateDelegatecallback.Target 문제를 해결하여, 대상 속성을 가지고있다.

람다의 대상은 실제로 클래스 인스턴스와 그것이 만지는 모든 로컬 변수 (디버거가 보여주는 것)에 대한 참조를 보유합니다.

이상한 점은 최신 .NET에서 작동한다는 것입니다. 모노와 .NET간에 약간의 차이가있을 수 있습니다.