2013-02-05 32 views
37

Tôi đang viết unit test cho một ứng dụng WinRT, và tôi có thể gọi phi async phương pháp tư nhân sử dụng này:Làm thế nào để chờ đợi một phương thức riêng tư async được gọi bằng cách sử dụng sự phản chiếu trong WinRT?

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

Tuy nhiên, nếu phương pháp tư nhân trong câu hỏi là async, mã sẽ tiếp tục thực hiện mà không đợi nó kết thúc.

Làm cách nào để thêm chức năng await vào tính năng này?

+0

Vì đây là một ứng dụng WinRT, tôi có cảm giác rằng sự phản ánh/yêu cầu của các thành viên riêng không được phép. Tôi không thể tìm thấy tài liệu chính thức về điều này trên google ngay bây giờ, gần nhất là: http://blogs.microsoft.co.il/blogs/sasha/archive/2011/09/17/metro-net-framework-profile-windows EDIT-EDITored.aspx: Đây là những bài kiểm tra đơn vị mặc dù, vì vậy có lẽ đó là một vấn đề không. :) –

+0

@Chris Sinclair Trên thực tế, mã tôi có ở trên hoạt động hoàn toàn tốt cho các phương pháp riêng tư. Vấn đề của tôi đặc biệt với vấn đề không đồng bộ. Vấn đề này cũng sẽ áp dụng cho các phương thức công khai được gọi thông qua sự phản chiếu. – jokeefe

Trả lời

69

Bạn cần phải sử dụng giá trị được trả về bằng phương pháp. Bạn có biết loại? Ví dụ, nếu nó luôn luôn là một Task, bạn có thể sử dụng:

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

Nếu bạn không biết những kiểu trả về nhưng biết nó sẽ được awaitable, bạn có thể sử dụng gõ động:

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

tôi hãy thử để tránh phải gọi phương thức riêng tư bằng cách phản ánh trong các thử nghiệm đơn vị của bạn ngay từ đầu. Bạn có thể kiểm tra nó gián tiếp thông qua API công cộng (hoặc nội bộ) không? Điều đó thường thích hợp hơn.

+0

Nhưng truyền sang 'dynamic' sẽ không hoạt động nếu' GetAwaiter() 'là một phương thức mở rộng, chính xác là trường hợp cho 'IAsyncAction' của WinRT. – svick

+0

@Jon Skeet: Cảm ơn! Điều này đã làm nó. Đó là một đối tượng 'Task' được trả về, vì vậy tất cả những gì tôi cần làm là cast nó và thêm' await'. Tôi cũng thấy rằng bạn cần phải làm cho kiểu trả về của phương thức kiểm tra đơn vị 'Task' cũng như khi bạn tạo nó thành 'async' hoặc nó sẽ không được thực thi bởi công việc khung kiểm thử đơn vị. – jokeefe

+0

@ Jeff: Sẽ giúp ích nếu bạn cung cấp thêm chi tiết, như lỗi trình biên dịch bạn đang nhận được. Nó cũng có thể có giá trị tạo ra một câu hỏi mới hơn là có một cuộc thảo luận bình luận về nó. –

6

Invoke phải trả về một đối tượng có thể chuyển đổi thành Task. Chỉ cần await đó.

Nếu phương thức riêng của bạn trả về void, thì bạn sẽ cần một tùy chỉnh SynchronizationContext, điều này rất lộn xộn. Tốt hơn là bạn nên trả lại các phương thức Task/Task<T>.

Các vấn đề liên quan