2013-02-05 2 views
37

I Unit-Tests für eine WinRT app ich schreibe, und ich bin in der Lage nicht-Asynchron-private Methoden aufrufen mit diesen:Wie erwartet man eine asynchrone private Methode, die durch Reflektion in WinRT aufgerufen wird?

TheObjectClass theObject = new TheObjectClass(); 
Type objType = typeof(TheObjectClass); 
objType.GetTypeInfo() 
     .GetDeclaredMethod("ThePrivateMethod") 
     .Invoke(theObject, null); 

Wenn jedoch die private Methode in Frage async ist, wird der Code-Ausführung weiter ohne darauf zu warten, dass es zu Ende geht.

Wie füge ich await Funktionalität zu diesem hinzu?

+0

Da dies eine WinRT App ist, habe ich das Gefühl, dass Reflektion/Aufruf von privaten Mitgliedern nicht erlaubt ist. Ich kann nicht offizielle Dokumentation von diesem auf Google im Augenblick finden, am nächsten ist: http://blogs.microsoft.co.il/blogs/sasha/archive/2011/09/17/metro-net-framework-profile-windows -tailored.aspx EDIT: Dies sind jedoch Unit-Tests, also ist es vielleicht kein Problem. :) –

+0

@Chris Sinclair Eigentlich funktioniert der Code, den ich oben habe, perfekt für private Methoden. Mein Problem ist speziell mit asynchronen. Das Problem würde auch für öffentliche Methoden gelten, die über Reflektion aufgerufen werden. – jokeefe

Antwort

69

Nun, Sie müssen den Wert verwenden, der von der Methode zurückgegeben wird. Kennst du den Typ? Zum Beispiel, wenn es immer ein Task ist, könnten Sie verwenden:

await (Task) objType.GetTypeInfo() 
        .GetDeclaredMethod("ThePrivateMethod") 
        .Invoke(theObject, null); 

Wenn Sie nicht wissen, den Rückgabetyp aber weiß, es wird sein awaitable, könnten Sie dynamische Typisierung:

await (dynamic) objType.GetTypeInfo() 
         .GetDeclaredMethod("ThePrivateMethod") 
         .Invoke(theObject, null); 

I würde versuchen zu vermeiden, eine private Methode durch Reflexion in Ihrem Unit-Tests in erster Linie zu rufen. Können Sie es indirekt über die öffentliche (oder interne) API testen? Das ist im Allgemeinen vorzuziehen.

+0

Die Umwandlung in 'dynamic' funktioniert jedoch nicht, wenn' GetAwaiter() 'eine Erweiterungsmethode ist, was genau für WinRT' IAsyncAction' der Fall ist. – svick

+0

@ Jon Skeet: Danke! Das hat es getan. Es war ein "Task" -Objekt, das zurückgegeben wurde, also musste ich es nur werfen und das "Warten" hinzufügen. Ich fand auch, dass Sie den Rückgabetyp "Task" der Einheitentestmethode auch machen müssen, wenn Sie es "async" machen, oder es wird nicht durch den Einheitentest-Rahmen ausgeführt. – jokeefe

+0

@Jeff: Es würde helfen, wenn Sie mehr Details geben würden, wie der Compiler-Fehler, den Sie bekommen. Es kann sich lohnen, eine neue Frage zu stellen, anstatt eine Diskussion darüber zu führen. –

6

Invoke sollte ein Objekt zurückgeben, das in Task konvertiert werden kann. Nur await das. Wenn Ihre private Methode void zurückgibt, benötigen Sie eine benutzerdefinierte SynchronizationContext, die unordentlich ist. Es ist besser, wenn Ihre Methoden Task/Task<T> zurückgeben.