2013-02-05 8 views
37

Sto scrittura di unit test per un'applicazione WinRT, e sono in grado di richiamare non asincrone metodi privati ​​di utilizzare questo:Come attendere un metodo privato asincrono invocato mediante reflection in WinRT?

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

Tuttavia, se il metodo privato in questione è async, il codice continuerà l'esecuzione senza aspettare che finisca.

Come si aggiunge la funzionalità await a questo?

+0

Poiché si tratta di un'app WinRT, ho la sensazione che la riflessione/l'invocazione di membri privati ​​non sia consentita. Non riesco a trovare la documentazione ufficiale di questo su google in questo momento, più vicino è: http://blogs.microsoft.co.il/blogs/sasha/archive/2011/09/17/metro-net-framework-profile-windows -tailored.aspx EDIT: Questi sono unit test, quindi forse è un non-problema. :) –

+0

@Chris Sinclair In realtà, il codice che ho sopra funziona perfettamente bene per i metodi privati. Il mio problema riguarda in particolare quelli asincroni. Il problema si applicherebbe ai metodi pubblici invocati tramite riflessione. – jokeefe

risposta

69

Bene, è necessario utilizzare il valore restituito dal metodo. Conosci il tipo? Ad esempio, se è sempre una Task, è possibile utilizzare:

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

Se non si conosce il tipo di ritorno, ma so che sarà awaitable, è possibile utilizzare la tipizzazione dinamica:

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

I Sarebbe provare per evitare di dover chiamare un metodo privato di riflessione nei test di unità in primo luogo però. Puoi testarlo indirettamente tramite l'API pubblica (o interna)? Questo è generalmente preferibile.

+0

Ma il cast in 'dynamic' non funzionerà se' GetAwaiter() 'è un metodo di estensione, che è esattamente il caso di WinRT' IAsyncAction'. – svick

+0

@Jon Skeet: Grazie! Questo è stato. Era un oggetto 'Task' che veniva restituito, quindi tutto ciò che dovevo fare era lanciarlo e aggiungere il' await'. Ho anche scoperto che è necessario rendere il tipo di ritorno del metodo unit test 'Task' anche quando lo si rende' async' o non verrà eseguito dal lavoro del frame di prova dell'unità. – jokeefe

+0

@Jeff: Sarebbe di grande aiuto se tu fornissi maggiori dettagli, come l'errore del compilatore che stai ottenendo. Potrebbe valere la pena di creare una nuova domanda piuttosto che avere una discussione di commento a riguardo. –

6

Invoke deve restituire un oggetto convertibile in Task. Solo await.

Se il metodo privato restituisce void, è necessario un codice personalizzato SynchronizationContext, che è disordinato. È meglio che i metodi restituiscano Task/Task<T>.

Problemi correlati