77namespace DotNetOpenAuth . Test {
88 using System ;
99 using System . Collections . Generic ;
10+ using System . Net ;
11+ using System . Net . Http ;
1012 using System . Threading ;
1113 using System . Threading . Tasks ;
1214 using DotNetOpenAuth . Messaging ;
@@ -15,40 +17,80 @@ namespace DotNetOpenAuth.Test {
1517 using NUnit . Framework ;
1618 using Validation ;
1719
18- internal abstract class CoordinatorBase < T1 , T2 > {
19- private Func < T1 , CancellationToken , Task > party1Action ;
20- private Func < T2 , CancellationToken , Task > party2Action ;
20+ using System . Linq ;
2121
22- protected CoordinatorBase ( Func < T1 , CancellationToken , Task > party1Action , Func < T2 , CancellationToken , Task > party2Action ) {
23- Requires . NotNull ( party1Action , "party1Action" ) ;
24- Requires . NotNull ( party2Action , "party2Action" ) ;
22+ internal class CoordinatorBase {
23+ private Func < IHostFactories , CancellationToken , Task > driver ;
2524
26- this . party1Action = party1Action ;
27- this . party2Action = party2Action ;
25+ private Handler [ ] handlers ;
26+
27+ internal CoordinatorBase ( Func < IHostFactories , CancellationToken , Task > driver , params Handler [ ] handlers ) {
28+ Requires . NotNull ( driver , "driver" ) ;
29+ Requires . NotNull ( handlers , "handlers" ) ;
30+
31+ this . driver = driver ;
32+ this . handlers = handlers ;
2833 }
2934
30- protected internal Action < IProtocolMessage > IncomingMessageFilter { get ; set ; }
35+ protected internal virtual async Task RunAsync ( CancellationToken cancellationToken = default ( CancellationToken ) ) {
36+ IHostFactories hostFactories = new MyHostFactories ( this . handlers ) ;
37+
38+ await this . driver ( hostFactories , cancellationToken ) ;
39+ }
3140
32- protected internal Action < IProtocolMessage > OutgoingMessageFilter { get ; set ; }
41+ internal static Handler Handle ( Uri uri ) {
42+ return new Handler ( uri ) ;
43+ }
3344
34- internal abstract Task RunAsync ( ) ;
45+ internal struct Handler {
46+ internal Handler ( Uri uri )
47+ : this ( ) {
48+ this . Uri = uri ;
49+ }
50+
51+ public Uri Uri { get ; private set ; }
52+
53+ public Func < HttpRequestMessage , CancellationToken , Task < HttpResponseMessage > > MessageHandler { get ; private set ; }
54+
55+ internal Handler By ( Func < HttpRequestMessage , CancellationToken , Task < HttpResponseMessage > > handler ) {
56+ return new Handler ( this . Uri ) { MessageHandler = handler } ;
57+ }
58+ }
3559
36- protected async Task RunCoreAsync ( T1 party1Object , T2 party2Object ) {
37- var cts = new CancellationTokenSource ( ) ;
60+ private class MyHostFactories : IHostFactories {
61+ private readonly Handler [ ] handlers ;
62+
63+ public MyHostFactories ( Handler [ ] handlers ) {
64+ this . handlers = handlers ;
65+ }
66+
67+ public HttpMessageHandler CreateHttpMessageHandler ( ) {
68+ return new ForwardingMessageHandler ( this . handlers ) ;
69+ }
70+
71+ public HttpClient CreateHttpClient ( HttpMessageHandler handler = null ) {
72+ return new HttpClient ( handler ?? this . CreateHttpMessageHandler ( ) ) ;
73+ }
74+ }
75+
76+ private class ForwardingMessageHandler : HttpMessageHandler {
77+ private readonly Handler [ ] handlers ;
78+
79+ public ForwardingMessageHandler ( Handler [ ] handlers ) {
80+ this . handlers = handlers ;
81+ }
3882
39- try {
40- var parties = new List < Task > {
41- Task . Run ( ( ) => this . party1Action ( party1Object , cts . Token ) ) ,
42- Task . Run ( ( ) => this . party2Action ( party2Object , cts . Token ) ) ,
43- } ;
44- var completingTask = await Task . WhenAny ( parties ) ;
45- await completingTask ; // rethrow any exception from the first completing task.
83+ protected override async Task < HttpResponseMessage > SendAsync ( HttpRequestMessage request , CancellationToken cancellationToken ) {
84+ foreach ( var handler in this . handlers ) {
85+ if ( handler . Uri . AbsolutePath == request . RequestUri . AbsolutePath ) {
86+ var response = await handler . MessageHandler ( request , cancellationToken ) ;
87+ if ( response != null ) {
88+ return response ;
89+ }
90+ }
91+ }
4692
47- // if no exception, then block for the second task now.
48- await Task . WhenAll ( parties ) ;
49- } catch {
50- cts . Cancel ( ) ; // cause the second party to terminate, if necessary.
51- throw ;
93+ return new HttpResponseMessage ( HttpStatusCode . NotFound ) ;
5294 }
5395 }
5496 }
0 commit comments