Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.ServiceModel / System / ServiceModel / ClientBase.cs
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4
5 namespace System.ServiceModel
6 {
7     using System.ComponentModel;
8     using System.Diagnostics;
9     using System.Runtime;
10     using System.ServiceModel.Channels;
11     using System.ServiceModel.Description;
12     using System.ServiceModel.Diagnostics;
13     using System.Threading;
14     using System.ServiceModel.Diagnostics.Application;
15     using System.Runtime.Remoting.Messaging;
16     using System.ServiceModel.Dispatcher;
17     using System.Security;
18
19     public abstract class ClientBase<TChannel> : ICommunicationObject, IDisposable
20         where TChannel : class
21     {
22         TChannel channel;
23         ChannelFactoryRef<TChannel> channelFactoryRef;
24         EndpointTrait<TChannel> endpointTrait;
25
26         // Determine whether the proxy can share factory with others. It is false only if the public getters
27         // are invoked.
28         bool canShareFactory = true;
29
30         // Determine whether the proxy is currently holding a cached factory
31         bool useCachedFactory;
32
33         // Determine whether we have locked down sharing for this proxy. This is turned on only when the channel
34         // is created.
35         bool sharingFinalized;
36
37         // Determine whether the ChannelFactoryRef has been released. We should release it only once per proxy
38         bool channelFactoryRefReleased;
39
40         // Determine whether we have released the last ref count of the ChannelFactory so that we could abort it when it was closing.
41         bool releasedLastRef;
42
43         object syncRoot = new object();
44
45         object finalizeLock = new object();
46
47         // Cache at most 32 ChannelFactories
48         const int maxNumChannelFactories = 32;
49         static ChannelFactoryRefCache<TChannel> factoryRefCache = new ChannelFactoryRefCache<TChannel>(maxNumChannelFactories);
50         static object staticLock = new object();
51
52         static object cacheLock = new object();
53         static CacheSetting cacheSetting = CacheSetting.Default;
54         static bool isCacheSettingReadOnly;
55
56         static AsyncCallback onAsyncCallCompleted = Fx.ThunkCallback(new AsyncCallback(OnAsyncCallCompleted));
57
58         // IMPORTANT: any changes to the set of protected .ctors of this class need to be reflected
59         // in ServiceContractGenerator.cs as well.
60
61         protected ClientBase()
62         {
63             MakeCacheSettingReadOnly();
64
65             if (cacheSetting == CacheSetting.AlwaysOff)
66             {
67                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>("*"));
68                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
69                 TryDisableSharing();
70             }
71             else
72             {
73                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>("*", null, null);
74                 InitializeChannelFactoryRef();
75             }
76         }
77
78         protected ClientBase(string endpointConfigurationName)
79         {
80             if (endpointConfigurationName == null)
81                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
82
83             MakeCacheSettingReadOnly();
84
85             if (cacheSetting == CacheSetting.AlwaysOff)
86             {
87                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>(endpointConfigurationName));
88                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
89                 TryDisableSharing();
90             }
91             else
92             {
93                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, null, null);
94                 InitializeChannelFactoryRef();
95             }
96         }
97
98         protected ClientBase(string endpointConfigurationName, string remoteAddress)
99         {
100             if (endpointConfigurationName == null)
101                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
102             if (remoteAddress == null)
103                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
104
105             MakeCacheSettingReadOnly();
106             EndpointAddress endpointAddress = new EndpointAddress(remoteAddress);
107
108             if (cacheSetting == CacheSetting.AlwaysOff)
109             {
110                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>(endpointConfigurationName, endpointAddress));
111                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
112                 TryDisableSharing();
113             }
114             else
115             {
116                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, endpointAddress, null);
117                 InitializeChannelFactoryRef();
118             }
119         }
120
121         protected ClientBase(string endpointConfigurationName, EndpointAddress remoteAddress)
122         {
123             if (endpointConfigurationName == null)
124                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
125             if (remoteAddress == null)
126                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
127
128             MakeCacheSettingReadOnly();
129
130             if (cacheSetting == CacheSetting.AlwaysOff)
131             {
132                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>(endpointConfigurationName, remoteAddress));
133                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
134                 TryDisableSharing();
135             }
136             else
137             {
138                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, remoteAddress, null);
139                 InitializeChannelFactoryRef();
140             }
141
142         }
143
144         protected ClientBase(Binding binding, EndpointAddress remoteAddress)
145         {
146             if (binding == null)
147                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
148             if (remoteAddress == null)
149                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
150
151             MakeCacheSettingReadOnly();
152
153             if (cacheSetting == CacheSetting.AlwaysOn)
154             {
155                 this.endpointTrait = new ProgrammaticEndpointTrait<TChannel>(binding, remoteAddress, null);
156                 InitializeChannelFactoryRef();
157             }
158             else
159             {
160                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>(binding, remoteAddress));
161                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
162                 TryDisableSharing();
163             }
164         }
165
166         protected ClientBase(ServiceEndpoint endpoint)
167         {
168             if (endpoint == null)
169                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
170
171             MakeCacheSettingReadOnly();
172
173             if (cacheSetting == CacheSetting.AlwaysOn)
174             {
175                 this.endpointTrait = new ServiceEndpointTrait<TChannel>(endpoint, null);
176                 this.InitializeChannelFactoryRef();
177             }
178             else
179             {
180                 channelFactoryRef = new ChannelFactoryRef<TChannel>(new ChannelFactory<TChannel>(endpoint));
181                 channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
182                 TryDisableSharing();
183             }
184         }
185
186         protected ClientBase(InstanceContext callbackInstance)
187         {
188             if (callbackInstance == null)
189                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
190
191             MakeCacheSettingReadOnly();
192
193             if (cacheSetting == CacheSetting.AlwaysOff)
194             {
195                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
196                     new DuplexChannelFactory<TChannel>(callbackInstance, "*"));
197                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
198                 TryDisableSharing();
199             }
200             else
201             {
202                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>("*", null, callbackInstance);
203                 InitializeChannelFactoryRef();
204             }
205         }
206
207         protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName)
208         {
209             if (callbackInstance == null)
210                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
211             if (endpointConfigurationName == null)
212                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
213
214             MakeCacheSettingReadOnly();
215
216             if (cacheSetting == CacheSetting.AlwaysOff)
217             {
218                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
219                     new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName));
220                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
221                 TryDisableSharing();
222             }
223             else
224             {
225                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, null, callbackInstance);
226                 InitializeChannelFactoryRef();
227             }
228         }
229
230         protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress)
231         {
232             if (callbackInstance == null)
233                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
234             if (endpointConfigurationName == null)
235                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
236             if (remoteAddress == null)
237                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
238
239             MakeCacheSettingReadOnly();
240             EndpointAddress endpointAddress = new EndpointAddress(remoteAddress);
241
242             if (cacheSetting == CacheSetting.AlwaysOff)
243             {
244                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
245                     new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName, endpointAddress));
246                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
247                 TryDisableSharing();
248             }
249             else
250             {
251                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, endpointAddress, callbackInstance);
252                 InitializeChannelFactoryRef();
253             }
254         }
255
256         protected ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress)
257         {
258             if (callbackInstance == null)
259                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
260             if (endpointConfigurationName == null)
261                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointConfigurationName");
262             if (remoteAddress == null)
263                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
264
265             MakeCacheSettingReadOnly();
266
267             if (cacheSetting == CacheSetting.AlwaysOff)
268             {
269                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
270                     new DuplexChannelFactory<TChannel>(callbackInstance, endpointConfigurationName, remoteAddress));
271                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
272                 TryDisableSharing();
273             }
274             else
275             {
276                 this.endpointTrait = new ConfigurationEndpointTrait<TChannel>(endpointConfigurationName, remoteAddress, callbackInstance);
277                 InitializeChannelFactoryRef();
278             }
279         }
280
281         protected ClientBase(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress)
282         {
283             if (callbackInstance == null)
284                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
285             if (binding == null)
286                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
287             if (remoteAddress == null)
288                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
289
290             MakeCacheSettingReadOnly();
291
292             if (cacheSetting == CacheSetting.AlwaysOn)
293             {
294                 this.endpointTrait = new ProgrammaticEndpointTrait<TChannel>(binding, remoteAddress, callbackInstance);
295                 InitializeChannelFactoryRef();
296             }
297             else
298             {
299                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
300                     new DuplexChannelFactory<TChannel>(callbackInstance, binding, remoteAddress));
301                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
302                 TryDisableSharing();
303             }
304         }
305
306         protected ClientBase(InstanceContext callbackInstance, ServiceEndpoint endpoint)
307         {
308             if (callbackInstance == null)
309                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
310             if (endpoint == null)
311                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
312
313             MakeCacheSettingReadOnly();
314
315             if (cacheSetting == CacheSetting.AlwaysOn)
316             {
317                 this.endpointTrait = new ServiceEndpointTrait<TChannel>(endpoint, callbackInstance);
318                 InitializeChannelFactoryRef();
319             }
320             else
321             {
322                 this.channelFactoryRef = new ChannelFactoryRef<TChannel>(
323                     new DuplexChannelFactory<TChannel>(callbackInstance, endpoint));
324                 this.channelFactoryRef.ChannelFactory.TraceOpenAndClose = false;
325                 TryDisableSharing();
326             }
327         }
328
329         protected T GetDefaultValueForInitialization<T>()
330         {
331             return default(T);
332         }
333
334         object ThisLock
335         {
336             get
337             {
338                 return syncRoot;
339             }
340         }
341
342         protected TChannel Channel
343         {
344             get
345             {
346                 // created on demand, so that Mort can modify .Endpoint before calling methods on the client
347                 if (this.channel == null)
348                 {
349                     lock (ThisLock)
350                     {
351                         if (this.channel == null)
352                         {
353                             using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
354                             {
355                                 if (DiagnosticUtility.ShouldUseActivity)
356                                 {
357                                     ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityOpenClientBase, typeof(TChannel).FullName), ActivityType.OpenClient);
358                                 }
359
360                                 if (this.useCachedFactory)
361                                 {
362                                     try
363                                     {
364                                         CreateChannelInternal();
365                                     }
366 #pragma warning suppress 56500 // covered by FxCOP
367                                     catch (Exception ex)
368                                     {
369                                         if (this.useCachedFactory &&
370                                             (ex is CommunicationException ||
371                                             ex is ObjectDisposedException ||
372                                             ex is TimeoutException))
373                                         {
374                                             DiagnosticUtility.TraceHandledException(ex, TraceEventType.Warning);
375                                             InvalidateCacheAndCreateChannel();
376                                         }
377                                         else
378                                         {
379 #pragma warning suppress 56503 // Microsoft, We throw only for unknown exceptions.
380                                             throw;
381                                         }
382                                     }
383                                 }
384                                 else
385                                 {
386                                     CreateChannelInternal();
387                                 }
388                             }
389                         }
390                     }
391                 }
392                 return channel;
393             }
394         }
395
396         public static CacheSetting CacheSetting
397         {
398             get
399             {
400                 return cacheSetting;
401             }
402             set
403             {
404                 lock (cacheLock)
405                 {
406                     if (isCacheSettingReadOnly && cacheSetting != value)
407                     {
408                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxImmutableClientBaseCacheSetting, typeof(TChannel).ToString())));
409                     }
410                     else
411                     {
412                         cacheSetting = value;
413                     }
414                 }
415             }
416         }
417
418         public ChannelFactory<TChannel> ChannelFactory
419         {
420             get
421             {
422                 if (cacheSetting == CacheSetting.Default)
423                 {
424                     TryDisableSharing();
425                 }
426                 return GetChannelFactory();
427             }
428         }
429
430         public ClientCredentials ClientCredentials
431         {
432             get
433             {
434                 if (cacheSetting == CacheSetting.Default)
435                 {
436                     TryDisableSharing();
437                 }
438                 return this.ChannelFactory.Credentials;
439             }
440         }
441
442         public CommunicationState State
443         {
444             get
445             {
446                 IChannel channel = (IChannel)this.channel;
447                 if (channel != null)
448                 {
449                     return channel.State;
450                 }
451                 else
452                 {
453                     // we may have failed to create the channel under open, in which case we our factory wouldn't be open
454                     if (!this.useCachedFactory)
455                     {
456                         return GetChannelFactory().State;
457                     }
458                     else
459                     {
460                         return CommunicationState.Created;
461                     }
462                 }
463             }
464         }
465
466         public IClientChannel InnerChannel
467         {
468             get
469             {
470                 return (IClientChannel)Channel;
471             }
472         }
473
474         public ServiceEndpoint Endpoint
475         {
476             get
477             {
478                 if (cacheSetting == CacheSetting.Default)
479                 {
480                     TryDisableSharing();
481                 }
482                 return GetChannelFactory().Endpoint;
483             }
484         }
485
486         public void Open()
487         {
488             ((ICommunicationObject)this).Open(GetChannelFactory().InternalOpenTimeout);
489         }
490
491         public void Abort()
492         {
493             IChannel channel = (IChannel)this.channel;
494             if (channel != null)
495             {
496                 channel.Abort();
497             }
498
499             if (!channelFactoryRefReleased)
500             {
501                 lock (staticLock)
502                 {
503                     if (!channelFactoryRefReleased)
504                     {
505                         if (this.channelFactoryRef.Release())
506                         {
507                             this.releasedLastRef = true;
508                         }
509
510                         channelFactoryRefReleased = true;
511                     }
512                 }
513             }
514
515             // Abort the ChannelFactory if we released the last one. We should be able to abort it when another thread is closing it.
516             if (this.releasedLastRef)
517             {
518                 this.channelFactoryRef.Abort();
519             }
520         }
521
522         public void Close()
523         {
524             ((ICommunicationObject)this).Close(GetChannelFactory().InternalCloseTimeout);
525         }
526
527         public void DisplayInitializationUI()
528         {
529             ((IClientChannel)this.InnerChannel).DisplayInitializationUI();
530         }
531
532         // This ensures that the cachesetting (on, off or default) cannot be modified by 
533         // another ClientBase instance of matching TChannel after the first instance is created.
534         void MakeCacheSettingReadOnly()
535         {
536             if (isCacheSettingReadOnly)
537                 return;
538
539             lock (cacheLock)
540             {
541                 isCacheSettingReadOnly = true;
542             }
543         }
544
545         void CreateChannelInternal()
546         {
547             try
548             {
549                 this.channel = this.CreateChannel();
550                 if (this.sharingFinalized)
551                 {
552                     if (this.canShareFactory && !this.useCachedFactory)
553                     {
554                         // It is OK to add ChannelFactory to the cache now.
555                         TryAddChannelFactoryToCache();
556                     }
557                 }
558             }
559             finally
560             {
561                 if (!this.sharingFinalized && cacheSetting == CacheSetting.Default)
562                 {
563                     // this.CreateChannel() is not called. For safety, we disable sharing.
564                     TryDisableSharing();
565                 }
566             }
567         }
568
569         protected virtual TChannel CreateChannel()
570         {
571             if (this.sharingFinalized)
572                 return GetChannelFactory().CreateChannel();
573
574             lock (this.finalizeLock)
575             {
576                 this.sharingFinalized = true;
577                 return GetChannelFactory().CreateChannel();
578             }
579         }
580
581         void IDisposable.Dispose()
582         {
583             this.Close();
584         }
585
586         void ICommunicationObject.Open(TimeSpan timeout)
587         {
588             TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
589             if (!this.useCachedFactory)
590             {
591                 GetChannelFactory().Open(timeoutHelper.RemainingTime());
592             }
593
594             this.InnerChannel.Open(timeoutHelper.RemainingTime());
595         }
596
597         void ICommunicationObject.Close(TimeSpan timeout)
598         {
599             using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
600             {
601                 if (DiagnosticUtility.ShouldUseActivity)
602                 {
603                     ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityCloseClientBase, typeof(TChannel).FullName), ActivityType.Close);
604                 }
605                 TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
606
607                 if (this.channel != null)
608                 {
609                     InnerChannel.Close(timeoutHelper.RemainingTime());
610                 }
611
612                 if (!channelFactoryRefReleased)
613                 {
614                     lock (staticLock)
615                     {
616                         if (!channelFactoryRefReleased)
617                         {
618                             if (this.channelFactoryRef.Release())
619                             {
620                                 this.releasedLastRef = true;
621                             }
622
623                             this.channelFactoryRefReleased = true;
624                         }
625                     }
626
627                     // Close the factory outside of the lock so that we can abort from a different thread.
628                     if (this.releasedLastRef)
629                     {
630                         if (this.useCachedFactory)
631                         {
632                             this.channelFactoryRef.Abort();
633                         }
634                         else
635                         {
636                             this.channelFactoryRef.Close(timeoutHelper.RemainingTime());
637                         }
638                     }
639                 }
640             }
641         }
642
643         event EventHandler ICommunicationObject.Closed
644         {
645             add
646             {
647                 this.InnerChannel.Closed += value;
648             }
649             remove
650             {
651                 this.InnerChannel.Closed -= value;
652             }
653         }
654
655         event EventHandler ICommunicationObject.Closing
656         {
657             add
658             {
659                 this.InnerChannel.Closing += value;
660             }
661             remove
662             {
663                 this.InnerChannel.Closing -= value;
664             }
665         }
666
667         event EventHandler ICommunicationObject.Faulted
668         {
669             add
670             {
671                 this.InnerChannel.Faulted += value;
672             }
673             remove
674             {
675                 this.InnerChannel.Faulted -= value;
676             }
677         }
678
679         event EventHandler ICommunicationObject.Opened
680         {
681             add
682             {
683                 this.InnerChannel.Opened += value;
684             }
685             remove
686             {
687                 this.InnerChannel.Opened -= value;
688             }
689         }
690
691         event EventHandler ICommunicationObject.Opening
692         {
693             add
694             {
695                 this.InnerChannel.Opening += value;
696             }
697             remove
698             {
699                 this.InnerChannel.Opening -= value;
700             }
701         }
702
703         IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state)
704         {
705             return ((ICommunicationObject)this).BeginClose(GetChannelFactory().InternalCloseTimeout, callback, state);
706         }
707
708         IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
709         {
710             return new ChainedAsyncResult(timeout, callback, state, BeginChannelClose, EndChannelClose, BeginFactoryClose, EndFactoryClose);
711         }
712
713         void ICommunicationObject.EndClose(IAsyncResult result)
714         {
715             ChainedAsyncResult.End(result);
716         }
717
718         IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state)
719         {
720             return ((ICommunicationObject)this).BeginOpen(GetChannelFactory().InternalOpenTimeout, callback, state);
721         }
722
723         IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
724         {
725             return new ChainedAsyncResult(timeout, callback, state, BeginFactoryOpen, EndFactoryOpen, BeginChannelOpen, EndChannelOpen);
726         }
727
728         void ICommunicationObject.EndOpen(IAsyncResult result)
729         {
730             ChainedAsyncResult.End(result);
731         }
732
733         //ChainedAsyncResult methods for opening and closing ChannelFactory<T>
734
735         internal IAsyncResult BeginFactoryOpen(TimeSpan timeout, AsyncCallback callback, object state)
736         {
737             if (this.useCachedFactory)
738             {
739                 return new CompletedAsyncResult(callback, state);
740             }
741             else
742             {
743                 return GetChannelFactory().BeginOpen(timeout, callback, state);
744             }
745         }
746
747         internal void EndFactoryOpen(IAsyncResult result)
748         {
749             if (this.useCachedFactory)
750             {
751                 CompletedAsyncResult.End(result);
752             }
753             else
754             {
755                 GetChannelFactory().EndOpen(result);
756             }
757         }
758
759         internal IAsyncResult BeginChannelOpen(TimeSpan timeout, AsyncCallback callback, object state)
760         {
761             return this.InnerChannel.BeginOpen(timeout, callback, state);
762         }
763
764         internal void EndChannelOpen(IAsyncResult result)
765         {
766             this.InnerChannel.EndOpen(result);
767         }
768
769         internal IAsyncResult BeginFactoryClose(TimeSpan timeout, AsyncCallback callback, object state)
770         {
771             if (this.useCachedFactory)
772             {
773                 return new CompletedAsyncResult(callback, state);
774             }
775             else
776             {
777                 return GetChannelFactory().BeginClose(timeout, callback, state);
778             }
779         }
780
781         internal void EndFactoryClose(IAsyncResult result)
782         {
783             if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
784             {
785                 CompletedAsyncResult.End(result);
786             }
787             else
788             {
789                 GetChannelFactory().EndClose(result);
790             }
791         }
792
793         internal IAsyncResult BeginChannelClose(TimeSpan timeout, AsyncCallback callback, object state)
794         {
795             if (this.channel != null)
796             {
797                 return this.InnerChannel.BeginClose(timeout, callback, state);
798             }
799             else
800             {
801                 return new CompletedAsyncResult(callback, state);
802             }
803         }
804
805         internal void EndChannelClose(IAsyncResult result)
806         {
807             if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
808             {
809                 CompletedAsyncResult.End(result);
810             }
811             else
812             {
813                 this.InnerChannel.EndClose(result);
814             }
815         }
816
817         ChannelFactory<TChannel> GetChannelFactory()
818         {
819             return this.channelFactoryRef.ChannelFactory;
820         }
821
822         void InitializeChannelFactoryRef()
823         {
824             Fx.Assert(this.channelFactoryRef == null, "The channelFactory should have never been assigned");
825             Fx.Assert(this.canShareFactory, "GetChannelFactoryFromCache can be called only when canShareFactory is true");
826             lock (staticLock)
827             {
828                 ChannelFactoryRef<TChannel> factoryRef;
829                 if (factoryRefCache.TryGetValue(this.endpointTrait, out factoryRef))
830                 {
831                     if (factoryRef.ChannelFactory.State != CommunicationState.Opened)
832                     {
833                         // Remove the bad ChannelFactory.
834                         factoryRefCache.Remove(this.endpointTrait);
835                     }
836                     else
837                     {
838                         this.channelFactoryRef = factoryRef;
839                         this.channelFactoryRef.AddRef();
840                         useCachedFactory = true;
841                         if (TD.ClientBaseChannelFactoryCacheHitIsEnabled())
842                         {
843                             TD.ClientBaseChannelFactoryCacheHit(this);
844                         }
845                         return;
846                     }
847                 }
848             }
849
850             if (this.channelFactoryRef == null)
851             {
852                 // Creating the ChannelFactory at initial time to catch configuration exception earlier.
853                 this.channelFactoryRef = CreateChannelFactoryRef(this.endpointTrait);
854             }
855         }
856
857         static ChannelFactoryRef<TChannel> CreateChannelFactoryRef(EndpointTrait<TChannel> endpointTrait)
858         {
859             Fx.Assert(endpointTrait != null, "The endpointTrait should not be null when the factory can be shared.");
860
861             ChannelFactory<TChannel> channelFactory = endpointTrait.CreateChannelFactory();
862             channelFactory.TraceOpenAndClose = false;
863             return new ChannelFactoryRef<TChannel>(channelFactory);
864         }
865
866         // Once the channel is created, we can't disable caching.
867         // This method can be called safely multiple times.  
868         // this.sharingFinalized is set the first time the method is called.
869         // Subsequent calls are essentially no-ops.
870         void TryDisableSharing()
871         {
872             if (this.sharingFinalized)
873                 return;
874
875             lock (this.finalizeLock)
876             {
877                 if (this.sharingFinalized)
878                     return;
879
880                 this.canShareFactory = false;
881                 this.sharingFinalized = true;
882
883                 if (this.useCachedFactory)
884                 {
885                     ChannelFactoryRef<TChannel> pendingFactoryRef = this.channelFactoryRef;
886                     this.channelFactoryRef = CreateChannelFactoryRef(this.endpointTrait);
887                     this.useCachedFactory = false;
888
889                     lock (staticLock)
890                     {
891                         if (!pendingFactoryRef.Release())
892                         {
893                             pendingFactoryRef = null;
894                         }
895                     }
896
897                     if (pendingFactoryRef != null)
898                         pendingFactoryRef.Abort();
899                 }
900             }
901
902             // can be done outside the lock since the lines below do not access shared data.
903             // also the use of this.sharingFinalized in the lines above ensures that tracing 
904             // happens only once and only when needed.
905             if (TD.ClientBaseUsingLocalChannelFactoryIsEnabled())
906             {
907                 TD.ClientBaseUsingLocalChannelFactory(this);
908             }
909         }
910
911         void TryAddChannelFactoryToCache()
912         {
913             Fx.Assert(this.canShareFactory, "This should be called only when this proxy can share ChannelFactory.");
914             Fx.Assert(this.channelFactoryRef.ChannelFactory.State == CommunicationState.Opened,
915                 "The ChannelFactory must be in Opened state for caching.");
916
917             // Lock the cache and add the item to synchronize with lookup.
918             lock (staticLock)
919             {
920                 ChannelFactoryRef<TChannel> cfRef;
921                 if (!factoryRefCache.TryGetValue(this.endpointTrait, out cfRef))
922                 {
923                     // Increment the ref count before adding to the cache.
924                     this.channelFactoryRef.AddRef();
925                     factoryRefCache.Add(this.endpointTrait, this.channelFactoryRef);
926                     this.useCachedFactory = true;
927                     if (TD.ClientBaseCachedChannelFactoryCountIsEnabled())
928                     {
929                         TD.ClientBaseCachedChannelFactoryCount(factoryRefCache.Count, maxNumChannelFactories, this);
930                     }
931                 }
932             }
933         }
934
935         // NOTE: This should be called inside ThisLock
936         void InvalidateCacheAndCreateChannel()
937         {
938             RemoveFactoryFromCache();
939             TryDisableSharing();
940             CreateChannelInternal();
941         }
942
943         void RemoveFactoryFromCache()
944         {
945             lock (staticLock)
946             {
947                 ChannelFactoryRef<TChannel> factoryRef;
948                 if (factoryRefCache.TryGetValue(this.endpointTrait, out factoryRef))
949                 {
950                     if (object.ReferenceEquals(this.channelFactoryRef, factoryRef))
951                     {
952                         factoryRefCache.Remove(this.endpointTrait);
953                     }
954                 }
955             }
956         }
957
958         // WARNING: changes in the signature/name of the following delegates must be applied to the 
959         // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
960         protected delegate IAsyncResult BeginOperationDelegate(object[] inValues, AsyncCallback asyncCallback, object state);
961         protected delegate object[] EndOperationDelegate(IAsyncResult result);
962
963         // WARNING: Any changes in the signature/name of the following type and its ctor must be applied to the 
964         // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
965         protected class InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs
966         {
967             object[] results;
968
969             internal InvokeAsyncCompletedEventArgs(object[] results, Exception error, bool cancelled, object userState)
970                 : base(error, cancelled, userState)
971             {
972                 this.results = results;
973             }
974
975             public object[] Results
976             {
977                 get
978                 {
979                     return this.results;
980                 }
981             }
982         }
983
984         // WARNING: Any changes in the signature/name of the following method ctor must be applied to the 
985         // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
986         protected void InvokeAsync(BeginOperationDelegate beginOperationDelegate, object[] inValues,
987             EndOperationDelegate endOperationDelegate, SendOrPostCallback operationCompletedCallback, object userState)
988         {
989             if (beginOperationDelegate == null)
990             {
991                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("beginOperationDelegate");
992             }
993             if (endOperationDelegate == null)
994             {
995                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endOperationDelegate");
996             }
997
998             AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(userState);
999             AsyncOperationContext context = new AsyncOperationContext(asyncOperation, endOperationDelegate, operationCompletedCallback);
1000
1001             Exception error = null;
1002             object[] results = null;
1003             IAsyncResult result = null;
1004             try
1005             {
1006                 result = beginOperationDelegate(inValues, onAsyncCallCompleted, context);
1007                 if (result.CompletedSynchronously)
1008                 {
1009                     results = endOperationDelegate(result);
1010                 }
1011             }
1012             catch (Exception e)
1013             {
1014                 if (Fx.IsFatal(e))
1015                 {
1016                     throw;
1017                 }
1018                 error = e;
1019             }
1020
1021             if (error != null || result.CompletedSynchronously) /* result cannot be null if error == null */
1022             {
1023                 CompleteAsyncCall(context, results, error);
1024             }
1025         }
1026
1027         static void OnAsyncCallCompleted(IAsyncResult result)
1028         {
1029             if (result.CompletedSynchronously)
1030             {
1031                 return;
1032             }
1033
1034             AsyncOperationContext context = (AsyncOperationContext)result.AsyncState;
1035             Exception error = null;
1036             object[] results = null;
1037             try
1038             {
1039                 results = context.EndDelegate(result);
1040             }
1041             catch (Exception e)
1042             {
1043                 if (Fx.IsFatal(e))
1044                 {
1045                     throw;
1046                 }
1047
1048                 error = e;
1049             }
1050
1051             CompleteAsyncCall(context, results, error);
1052         }
1053
1054         static void CompleteAsyncCall(AsyncOperationContext context, object[] results, Exception error)
1055         {
1056             if (context.CompletionCallback != null)
1057             {
1058                 InvokeAsyncCompletedEventArgs e = new InvokeAsyncCompletedEventArgs(results, error, false, context.AsyncOperation.UserSuppliedState);
1059                 context.AsyncOperation.PostOperationCompleted(context.CompletionCallback, e);
1060             }
1061             else
1062             {
1063                 context.AsyncOperation.OperationCompleted();
1064             }
1065         }
1066
1067         class AsyncOperationContext
1068         {
1069             AsyncOperation asyncOperation;
1070             EndOperationDelegate endDelegate;
1071             SendOrPostCallback completionCallback;
1072
1073             internal AsyncOperationContext(AsyncOperation asyncOperation, EndOperationDelegate endDelegate, SendOrPostCallback completionCallback)
1074             {
1075                 this.asyncOperation = asyncOperation;
1076                 this.endDelegate = endDelegate;
1077                 this.completionCallback = completionCallback;
1078             }
1079
1080             internal AsyncOperation AsyncOperation
1081             {
1082                 get
1083                 {
1084                     return this.asyncOperation;
1085                 }
1086             }
1087
1088             internal EndOperationDelegate EndDelegate
1089             {
1090                 get
1091                 {
1092                     return this.endDelegate;
1093                 }
1094             }
1095
1096             internal SendOrPostCallback CompletionCallback
1097             {
1098                 get
1099                 {
1100                     return this.completionCallback;
1101                 }
1102             }
1103         }
1104
1105         protected class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel, IChannelBaseProxy
1106             where T : class
1107         {
1108             ServiceChannel channel;
1109             System.ServiceModel.Dispatcher.ImmutableClientRuntime runtime;
1110
1111             protected ChannelBase(ClientBase<T> client)
1112             {
1113                 if (client.Endpoint.Address == null)
1114                 {
1115                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxChannelFactoryEndpointAddressUri)));
1116                 }
1117
1118                 ChannelFactory<T> cf = client.ChannelFactory;
1119                 cf.EnsureOpened();  // to prevent the NullReferenceException that is thrown if the ChannelFactory is not open when cf.ServiceChannelFactory is accessed.
1120                 this.channel = cf.ServiceChannelFactory.CreateServiceChannel(client.Endpoint.Address, client.Endpoint.Address.Uri);
1121                 this.channel.InstanceContext = cf.CallbackInstance;
1122                 this.runtime = this.channel.ClientRuntime.GetRuntime();
1123             }
1124
1125             [Fx.Tag.SecurityNote(Critical = "Accesses the critical IMethodCallMessage interface.",
1126                 Safe = "The implementation of IMethodCallMessage is local and is created locally as weell; i.e. not passed in from Remoting.")]
1127             [SecuritySafeCritical]
1128             protected IAsyncResult BeginInvoke(string methodName, object[] args, AsyncCallback callback, object state)
1129             {
1130                 object[] inArgs = new object[args.Length + 2];
1131                 Array.Copy(args, inArgs, args.Length);
1132                 inArgs[inArgs.Length - 2] = callback;
1133                 inArgs[inArgs.Length - 1] = state;
1134
1135                 IMethodCallMessage methodCall = new MethodCallMessage(inArgs);
1136                 ProxyOperationRuntime op = GetOperationByName(methodName);
1137                 object[] ins = op.MapAsyncBeginInputs(methodCall, out callback, out state);
1138                 return this.channel.BeginCall(op.Action, op.IsOneWay, op, ins, callback, state);
1139             }
1140
1141             [Fx.Tag.SecurityNote(Critical = "Accesses the critical IMethodCallMessage interface.",
1142                 Safe = "The implementation of IMethodCallMessage is local and is created locally as weell; i.e. not passed in from Remoting.")]
1143             [SecuritySafeCritical]
1144             protected object EndInvoke(string methodName, object[] args, IAsyncResult result)
1145             {
1146                 object[] inArgs = new object[args.Length + 1];
1147                 Array.Copy(args, inArgs, args.Length);
1148                 inArgs[inArgs.Length - 1] = result;
1149
1150                 IMethodCallMessage methodCall = new MethodCallMessage(inArgs);
1151                 ProxyOperationRuntime op = GetOperationByName(methodName);
1152                 object[] outs;
1153                 op.MapAsyncEndInputs(methodCall, out result, out outs);
1154                 object ret = this.channel.EndCall(op.Action, outs, result);
1155                 object[] retArgs = op.MapAsyncOutputs(methodCall, outs, ref ret);
1156                 if (retArgs != null)
1157                 {
1158                     Fx.Assert(retArgs.Length == inArgs.Length, "retArgs.Length should be equal to inArgs.Length");
1159                     Array.Copy(retArgs, args, args.Length);
1160                 }
1161                 return ret;
1162             }
1163
1164             System.ServiceModel.Dispatcher.ProxyOperationRuntime GetOperationByName(string methodName)
1165             {
1166                 ProxyOperationRuntime op = this.runtime.GetOperationByName(methodName);
1167                 if (op == null)
1168                 {
1169                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupported1, methodName)));
1170                 }
1171                 return op;
1172             }
1173
1174             bool IClientChannel.AllowInitializationUI
1175             {
1176                 get { return ((IClientChannel)this.channel).AllowInitializationUI; }
1177                 set { ((IClientChannel)this.channel).AllowInitializationUI = value; }
1178             }
1179
1180             bool IClientChannel.DidInteractiveInitialization
1181             {
1182                 get { return ((IClientChannel)this.channel).DidInteractiveInitialization; }
1183             }
1184
1185             Uri IClientChannel.Via
1186             {
1187                 get { return ((IClientChannel)this.channel).Via; }
1188             }
1189
1190             event EventHandler<UnknownMessageReceivedEventArgs> IClientChannel.UnknownMessageReceived
1191             {
1192                 add { ((IClientChannel)this.channel).UnknownMessageReceived += value; }
1193                 remove { ((IClientChannel)this.channel).UnknownMessageReceived -= value; }
1194             }
1195
1196             void IClientChannel.DisplayInitializationUI()
1197             {
1198                 ((IClientChannel)this.channel).DisplayInitializationUI();
1199             }
1200
1201             IAsyncResult IClientChannel.BeginDisplayInitializationUI(AsyncCallback callback, object state)
1202             {
1203                 return ((IClientChannel)this.channel).BeginDisplayInitializationUI(callback, state);
1204             }
1205
1206             void IClientChannel.EndDisplayInitializationUI(IAsyncResult result)
1207             {
1208                 ((IClientChannel)this.channel).EndDisplayInitializationUI(result);
1209             }
1210
1211             bool IContextChannel.AllowOutputBatching
1212             {
1213                 get { return ((IContextChannel)this.channel).AllowOutputBatching; }
1214                 set { ((IContextChannel)this.channel).AllowOutputBatching = value; }
1215             }
1216
1217             IInputSession IContextChannel.InputSession
1218             {
1219                 get { return ((IContextChannel)this.channel).InputSession; }
1220             }
1221
1222             EndpointAddress IContextChannel.LocalAddress
1223             {
1224                 get { return ((IContextChannel)this.channel).LocalAddress; }
1225             }
1226
1227             TimeSpan IContextChannel.OperationTimeout
1228             {
1229                 get { return ((IContextChannel)this.channel).OperationTimeout; }
1230                 set { ((IContextChannel)this.channel).OperationTimeout = value; }
1231             }
1232
1233             IOutputSession IContextChannel.OutputSession
1234             {
1235                 get { return ((IContextChannel)this.channel).OutputSession; }
1236             }
1237
1238             EndpointAddress IContextChannel.RemoteAddress
1239             {
1240                 get { return ((IContextChannel)this.channel).RemoteAddress; }
1241             }
1242
1243             string IContextChannel.SessionId
1244             {
1245                 get { return ((IContextChannel)this.channel).SessionId; }
1246             }
1247
1248             TProperty IChannel.GetProperty<TProperty>()
1249             {
1250                 return ((IChannel)this.channel).GetProperty<TProperty>();
1251             }
1252
1253             CommunicationState ICommunicationObject.State
1254             {
1255                 get { return ((ICommunicationObject)this.channel).State; }
1256             }
1257
1258             event EventHandler ICommunicationObject.Closed
1259             {
1260                 add { ((ICommunicationObject)this.channel).Closed += value; }
1261                 remove { ((ICommunicationObject)this.channel).Closed -= value; }
1262             }
1263
1264             event EventHandler ICommunicationObject.Closing
1265             {
1266                 add { ((ICommunicationObject)this.channel).Closing += value; }
1267                 remove { ((ICommunicationObject)this.channel).Closing -= value; }
1268             }
1269
1270             event EventHandler ICommunicationObject.Faulted
1271             {
1272                 add { ((ICommunicationObject)this.channel).Faulted += value; }
1273                 remove { ((ICommunicationObject)this.channel).Faulted -= value; }
1274             }
1275
1276             event EventHandler ICommunicationObject.Opened
1277             {
1278                 add { ((ICommunicationObject)this.channel).Opened += value; }
1279                 remove { ((ICommunicationObject)this.channel).Opened -= value; }
1280             }
1281
1282             event EventHandler ICommunicationObject.Opening
1283             {
1284                 add { ((ICommunicationObject)this.channel).Opening += value; }
1285                 remove { ((ICommunicationObject)this.channel).Opening -= value; }
1286             }
1287
1288             void ICommunicationObject.Abort()
1289             {
1290                 ((ICommunicationObject)this.channel).Abort();
1291             }
1292
1293             void ICommunicationObject.Close()
1294             {
1295                 ((ICommunicationObject)this.channel).Close();
1296             }
1297
1298             void ICommunicationObject.Close(TimeSpan timeout)
1299             {
1300                 ((ICommunicationObject)this.channel).Close(timeout);
1301             }
1302
1303             IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state)
1304             {
1305                 return ((ICommunicationObject)this.channel).BeginClose(callback, state);
1306             }
1307
1308             IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
1309             {
1310                 return ((ICommunicationObject)this.channel).BeginClose(timeout, callback, state);
1311             }
1312
1313             void ICommunicationObject.EndClose(IAsyncResult result)
1314             {
1315                 ((ICommunicationObject)this.channel).EndClose(result);
1316             }
1317
1318             void ICommunicationObject.Open()
1319             {
1320                 ((ICommunicationObject)this.channel).Open();
1321             }
1322
1323             void ICommunicationObject.Open(TimeSpan timeout)
1324             {
1325                 ((ICommunicationObject)this.channel).Open(timeout);
1326             }
1327
1328             IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state)
1329             {
1330                 return ((ICommunicationObject)this.channel).BeginOpen(callback, state);
1331             }
1332
1333             IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
1334             {
1335                 return ((ICommunicationObject)this.channel).BeginOpen(timeout, callback, state);
1336             }
1337
1338             void ICommunicationObject.EndOpen(IAsyncResult result)
1339             {
1340                 ((ICommunicationObject)this.channel).EndOpen(result);
1341             }
1342
1343             IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions
1344             {
1345                 get { return ((IExtensibleObject<IContextChannel>)this.channel).Extensions; }
1346             }
1347
1348             void IDisposable.Dispose()
1349             {
1350                 ((IDisposable)this.channel).Dispose();
1351             }
1352
1353             Uri IOutputChannel.Via
1354             {
1355                 get { return ((IOutputChannel)this.channel).Via; }
1356             }
1357
1358             EndpointAddress IOutputChannel.RemoteAddress
1359             {
1360                 get { return ((IOutputChannel)this.channel).RemoteAddress; }
1361             }
1362
1363             void IOutputChannel.Send(Message message)
1364             {
1365                 ((IOutputChannel)this.channel).Send(message);
1366             }
1367
1368             void IOutputChannel.Send(Message message, TimeSpan timeout)
1369             {
1370                 ((IOutputChannel)this.channel).Send(message, timeout);
1371             }
1372
1373             IAsyncResult IOutputChannel.BeginSend(Message message, AsyncCallback callback, object state)
1374             {
1375                 return ((IOutputChannel)this.channel).BeginSend(message, callback, state);
1376             }
1377
1378             IAsyncResult IOutputChannel.BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
1379             {
1380                 return ((IOutputChannel)this.channel).BeginSend(message, timeout, callback, state);
1381             }
1382
1383             void IOutputChannel.EndSend(IAsyncResult result)
1384             {
1385                 ((IOutputChannel)this.channel).EndSend(result);
1386             }
1387
1388             Uri IRequestChannel.Via
1389             {
1390                 get { return ((IRequestChannel)this.channel).Via; }
1391             }
1392
1393             EndpointAddress IRequestChannel.RemoteAddress
1394             {
1395                 get { return ((IRequestChannel)this.channel).RemoteAddress; }
1396             }
1397
1398             Message IRequestChannel.Request(Message message)
1399             {
1400                 return ((IRequestChannel)this.channel).Request(message);
1401             }
1402
1403             Message IRequestChannel.Request(Message message, TimeSpan timeout)
1404             {
1405                 return ((IRequestChannel)this.channel).Request(message, timeout);
1406             }
1407
1408             IAsyncResult IRequestChannel.BeginRequest(Message message, AsyncCallback callback, object state)
1409             {
1410                 return ((IRequestChannel)this.channel).BeginRequest(message, callback, state);
1411             }
1412
1413             IAsyncResult IRequestChannel.BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
1414             {
1415                 return ((IRequestChannel)this.channel).BeginRequest(message, timeout, callback, state);
1416             }
1417
1418             Message IRequestChannel.EndRequest(IAsyncResult result)
1419             {
1420                 return ((IRequestChannel)this.channel).EndRequest(result);
1421             }
1422
1423             ServiceChannel IChannelBaseProxy.GetServiceChannel()
1424             {
1425                 return this.channel;
1426             }
1427
1428             class MethodCallMessage : IMethodCallMessage
1429             {
1430                 readonly object[] args;
1431
1432                 public MethodCallMessage(object[] args)
1433                 {
1434                     this.args = args;
1435                 }
1436
1437                 public object[] Args
1438                 {
1439                     get { return this.args; }
1440                 }
1441
1442                 public int ArgCount
1443                 {
1444                     get { return this.args.Length; }
1445                 }
1446
1447                 public LogicalCallContext LogicalCallContext
1448                 {
1449                     get { return null; }
1450                 }
1451
1452                 public object GetInArg(int argNum)
1453                 {
1454                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1455                 }
1456
1457                 public string GetInArgName(int index)
1458                 {
1459                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1460                 }
1461
1462                 public int InArgCount
1463                 {
1464                     get
1465                     {
1466                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1467                     }
1468                 }
1469
1470                 public object[] InArgs
1471                 {
1472                     get { return this.args; }
1473                 }
1474
1475
1476                 public object GetArg(int argNum)
1477                 {
1478                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1479                 }
1480
1481                 public string GetArgName(int index)
1482                 {
1483                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1484                 }
1485
1486                 public bool HasVarArgs
1487                 {
1488                     get
1489                     {
1490                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1491                     }
1492                 }
1493
1494                 public Reflection.MethodBase MethodBase
1495                 {
1496                     get
1497                     {
1498                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1499                     }
1500                 }
1501
1502                 public string MethodName
1503                 {
1504                     get
1505                     {
1506                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1507                     }
1508                 }
1509
1510                 public object MethodSignature
1511                 {
1512                     get
1513                     {
1514                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1515                     }
1516                 }
1517
1518                 public string TypeName
1519                 {
1520                     get
1521                     {
1522                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1523                     }
1524                 }
1525
1526                 public string Uri
1527                 {
1528                     get
1529                     {
1530                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1531                     }
1532                 }
1533
1534                 public Collections.IDictionary Properties
1535                 {
1536                     get
1537                     {
1538                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
1539                     }
1540                 }
1541             }
1542         }
1543     }
1544 }