2 // generic ClientBase.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005-2006 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.ComponentModel;
31 using System.ServiceModel.Channels;
32 using System.ServiceModel.Description;
33 using System.ServiceModel.Dispatcher;
34 using System.Threading;
36 namespace System.ServiceModel
38 [MonoTODO ("It somehow rejects classes, but dunno how we can do that besides our code level.")]
39 public abstract class ClientBase<TChannel>
40 : IDisposable, ICommunicationObject
42 static InstanceContext initialContxt = new InstanceContext (null);
44 ChannelFactory<TChannel> factory;
45 ClientRuntimeChannel inner_channel;
46 CommunicationState state;
48 protected delegate IAsyncResult BeginOperationDelegate (object[] inValues, AsyncCallback asyncCallback, object state);
49 protected delegate object[] EndOperationDelegate (IAsyncResult result);
51 protected ClientBase ()
52 : this (initialContxt)
56 protected ClientBase (string endpointConfigurationName)
57 : this (initialContxt, endpointConfigurationName)
61 protected ClientBase (Binding binding, EndpointAddress remoteAddress)
62 : this (initialContxt, binding, remoteAddress)
66 protected ClientBase (string endpointConfigurationName, EndpointAddress remoteAddress)
67 : this (initialContxt, endpointConfigurationName, remoteAddress)
71 protected ClientBase (string endpointConfigurationName, string remoteAddress)
72 : this (initialContxt, endpointConfigurationName, remoteAddress)
76 protected ClientBase (InstanceContext instance)
77 : this (instance, "*")
81 protected ClientBase (InstanceContext instance, string endpointConfigurationName)
84 throw new ArgumentNullException ("instanceContext");
85 if (endpointConfigurationName == null)
86 throw new ArgumentNullException ("endpointConfigurationName");
88 Initialize (instance, endpointConfigurationName, null);
91 protected ClientBase (InstanceContext instance,
92 string endpointConfigurationName, EndpointAddress remoteAddress)
95 throw new ArgumentNullException ("instanceContext");
96 if (endpointConfigurationName == null)
97 throw new ArgumentNullException ("endpointConfigurationName");
98 if (remoteAddress == null)
99 throw new ArgumentNullException ("remoteAddress");
101 Initialize (instance, endpointConfigurationName, remoteAddress);
104 protected ClientBase (InstanceContext instance,
105 string endpointConfigurationName, string remoteAddress)
107 if (instance == null)
108 throw new ArgumentNullException ("instanceContext");
109 if (remoteAddress == null)
110 throw new ArgumentNullException ("endpointAddress");
111 if (endpointConfigurationName == null)
112 throw new ArgumentNullException ("endpointConfigurationName");
114 Initialize (instance, endpointConfigurationName, new EndpointAddress (remoteAddress));
117 protected ClientBase (InstanceContext instance,
118 Binding binding, EndpointAddress remoteAddress)
120 if (instance == null)
121 throw new ArgumentNullException ("instanceContext");
123 throw new ArgumentNullException ("binding");
124 if (remoteAddress == null)
125 throw new ArgumentNullException ("remoteAddress");
127 Initialize (instance, binding, remoteAddress);
130 void Initialize (InstanceContext instance,
131 string endpointConfigurationName, EndpointAddress remoteAddress)
133 factory = new ChannelFactory<TChannel> (endpointConfigurationName, remoteAddress);
136 void Initialize (InstanceContext instance,
137 Binding binding, EndpointAddress remoteAddress)
139 factory = new ChannelFactory<TChannel> (binding, remoteAddress);
142 public ChannelFactory<TChannel> ChannelFactory {
143 get { return factory; }
147 public ClientCredentials ClientCredentials {
148 get { return ChannelFactory.Credentials; }
152 public ServiceEndpoint Endpoint {
153 get { return factory.Endpoint; }
156 public IClientChannel InnerChannel {
158 if (inner_channel == null)
159 inner_channel = (ClientRuntimeChannel) (object) factory.CreateChannel ();
160 return inner_channel;
164 protected TChannel Channel {
165 get { return (TChannel) (object) InnerChannel; }
168 public CommunicationState State {
169 get { return InnerChannel.State; }
174 InnerChannel.Abort ();
179 InnerChannel.Close ();
182 public void DisplayInitializationUI ()
184 InnerChannel.DisplayInitializationUI ();
188 IAsyncResult delegate_async;
190 protected void InvokeAsync (BeginOperationDelegate beginOperationDelegate,
191 object [] inValues, EndOperationDelegate endOperationDelegate,
192 SendOrPostCallback operationCompletedCallback, object userState)
194 if (beginOperationDelegate == null)
195 throw new ArgumentNullException ("beginOperationDelegate");
196 if (endOperationDelegate == null)
197 throw new ArgumentNullException ("endOperationDelegate");
198 if (delegate_async != null)
199 throw new InvalidOperationException ("Another async operation is in progress");
201 var bw = new BackgroundWorker ();
202 bw.DoWork += delegate (object o, DoWorkEventArgs e) {
203 delegate_async = beginOperationDelegate (inValues, null, userState);
205 bw.RunWorkerCompleted += delegate (object o, RunWorkerCompletedEventArgs e) {
206 var ret = endOperationDelegate (delegate_async);
207 if (operationCompletedCallback != null)
208 operationCompletedCallback (ret);
209 delegate_async = null;
211 bw.RunWorkerAsync ();
215 void IDisposable.Dispose ()
220 protected virtual TChannel CreateChannel ()
222 return ChannelFactory.CreateChannel ();
227 InnerChannel.Open ();
230 #region ICommunicationObject implementation
233 IAsyncResult ICommunicationObject.BeginOpen (
234 AsyncCallback callback, object state)
236 return InnerChannel.BeginOpen (callback, state);
240 IAsyncResult ICommunicationObject.BeginOpen (
241 TimeSpan timeout, AsyncCallback callback, object state)
243 return InnerChannel.BeginOpen (timeout, callback, state);
247 void ICommunicationObject.EndOpen (IAsyncResult result)
249 InnerChannel.EndOpen (result);
253 IAsyncResult ICommunicationObject.BeginClose (
254 AsyncCallback callback, object state)
256 return InnerChannel.BeginClose (callback, state);
260 IAsyncResult ICommunicationObject.BeginClose (
261 TimeSpan timeout, AsyncCallback callback, object state)
263 return InnerChannel.BeginClose (timeout, callback, state);
267 void ICommunicationObject.EndClose (IAsyncResult result)
269 InnerChannel.EndClose (result);
273 void ICommunicationObject.Close (TimeSpan timeout)
275 InnerChannel.Close (timeout);
279 void ICommunicationObject.Open (TimeSpan timeout)
281 InnerChannel.Open (timeout);
284 event EventHandler ICommunicationObject.Opening {
285 add { InnerChannel.Opening += value; }
286 remove { InnerChannel.Opening -= value; }
288 event EventHandler ICommunicationObject.Opened {
289 add { InnerChannel.Opened += value; }
290 remove { InnerChannel.Opened -= value; }
292 event EventHandler ICommunicationObject.Closing {
293 add { InnerChannel.Closing += value; }
294 remove { InnerChannel.Closing -= value; }
296 event EventHandler ICommunicationObject.Closed {
297 add { InnerChannel.Closed += value; }
298 remove { InnerChannel.Closed -= value; }
300 event EventHandler ICommunicationObject.Faulted {
301 add { InnerChannel.Faulted += value; }
302 remove { InnerChannel.Faulted -= value; }
308 protected class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel where T : class
310 ClientBase<T> client;
312 protected ChannelBase (ClientBase<T> client)
314 this.client = client;
318 protected IAsyncResult BeginInvoke (string methodName, object [] args, AsyncCallback callback, object state)
320 throw new NotImplementedException ();
324 protected object EndInvoke (string methodName, object [] args, IAsyncResult result)
326 throw new NotImplementedException ();
329 #region ICommunicationObject
331 IAsyncResult ICommunicationObject.BeginClose (AsyncCallback callback, object state)
333 return client.InnerChannel.BeginClose (callback, state);
336 IAsyncResult ICommunicationObject.BeginClose (TimeSpan timeout, AsyncCallback callback, object state)
338 return client.InnerChannel.BeginClose (timeout, callback, state);
341 void ICommunicationObject.Close ()
343 client.InnerChannel.Close ();
346 void ICommunicationObject.Close (TimeSpan timeout)
348 client.InnerChannel.Close (timeout);
351 IAsyncResult ICommunicationObject.BeginOpen (AsyncCallback callback, object state)
353 return client.InnerChannel.BeginOpen (callback, state);
356 IAsyncResult ICommunicationObject.BeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
358 return client.InnerChannel.BeginOpen (timeout, callback, state);
361 void ICommunicationObject.Open ()
363 client.InnerChannel.Open ();
366 void ICommunicationObject.Open (TimeSpan timeout)
368 client.InnerChannel.Open (timeout);
371 void ICommunicationObject.Abort ()
373 client.InnerChannel.Abort ();
376 void ICommunicationObject.EndClose (IAsyncResult result)
378 client.InnerChannel.EndClose (result);
381 void ICommunicationObject.EndOpen (IAsyncResult result)
383 client.InnerChannel.EndOpen (result);
386 CommunicationState ICommunicationObject.State {
387 get { return client.InnerChannel.State; }
390 event EventHandler ICommunicationObject.Opened {
391 add { client.InnerChannel.Opened += value; }
392 remove { client.InnerChannel.Opened -= value; }
395 event EventHandler ICommunicationObject.Opening {
396 add { client.InnerChannel.Opening += value; }
397 remove { client.InnerChannel.Opening -= value; }
400 event EventHandler ICommunicationObject.Closed {
401 add { client.InnerChannel.Closed += value; }
402 remove { client.InnerChannel.Closed -= value; }
405 event EventHandler ICommunicationObject.Closing {
406 add { client.InnerChannel.Closing += value; }
407 remove { client.InnerChannel.Closing -= value; }
410 event EventHandler ICommunicationObject.Faulted {
411 add { client.InnerChannel.Faulted += value; }
412 remove { client.InnerChannel.Faulted -= value; }
417 #region IClientChannel
419 public bool AllowInitializationUI {
420 get { return client.InnerChannel.AllowInitializationUI; }
421 set { client.InnerChannel.AllowInitializationUI = value; }
424 public bool DidInteractiveInitialization {
425 get { return client.InnerChannel.DidInteractiveInitialization; }
429 get { return client.InnerChannel.Via; }
432 public IAsyncResult BeginDisplayInitializationUI (
433 AsyncCallback callback, object state)
435 return client.InnerChannel.BeginDisplayInitializationUI (callback, state);
438 public void EndDisplayInitializationUI (
441 client.InnerChannel.EndDisplayInitializationUI (result);
444 public void DisplayInitializationUI ()
446 client.InnerChannel.DisplayInitializationUI ();
449 public void Dispose ()
451 client.InnerChannel.Dispose ();
454 public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived {
455 add { client.InnerChannel.UnknownMessageReceived += value; }
456 remove { client.InnerChannel.UnknownMessageReceived -= value; }
461 #region IContextChannel
464 public bool AllowOutputBatching {
465 get { return client.InnerChannel.AllowOutputBatching; }
467 set { client.InnerChannel.AllowOutputBatching = value; }
471 public IInputSession InputSession {
472 get { return client.InnerChannel.InputSession; }
476 public EndpointAddress LocalAddress {
477 get { return client.InnerChannel.LocalAddress; }
481 public TimeSpan OperationTimeout {
482 get { return client.InnerChannel.OperationTimeout; }
483 set { client.InnerChannel.OperationTimeout = value; }
487 public IOutputSession OutputSession {
488 get { return client.InnerChannel.OutputSession; }
492 public EndpointAddress RemoteAddress {
493 get { return client.InnerChannel.RemoteAddress; }
497 public string SessionId {
498 get { return client.InnerChannel.SessionId; }
505 IAsyncResult IRequestChannel.BeginRequest (Message message, AsyncCallback callback, object state)
507 throw new NotImplementedException ();
511 IAsyncResult IRequestChannel.BeginRequest (Message message, TimeSpan timeout, AsyncCallback callback, object state)
513 throw new NotImplementedException ();
517 Message IRequestChannel.EndRequest (IAsyncResult result)
519 throw new NotImplementedException ();
523 Message IRequestChannel.Request (Message message)
525 throw new NotImplementedException ();
529 Message IRequestChannel.Request (Message message, TimeSpan timeout)
531 throw new NotImplementedException ();
535 EndpointAddress IRequestChannel.RemoteAddress {
536 get { throw new NotImplementedException (); }
540 Uri IRequestChannel.Via {
541 get { throw new NotImplementedException (); }
545 IAsyncResult IOutputChannel.BeginSend (Message message, AsyncCallback callback, object state)
547 throw new NotImplementedException ();
551 IAsyncResult IOutputChannel.BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
553 throw new NotImplementedException ();
557 void IOutputChannel.EndSend (IAsyncResult result)
559 throw new NotImplementedException ();
563 void IOutputChannel.Send (Message message)
565 throw new NotImplementedException ();
569 void IOutputChannel.Send (Message message, TimeSpan timeout)
571 throw new NotImplementedException ();
575 IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions {
576 get { return client.InnerChannel.Extensions; }
580 TProperty IChannel.GetProperty<TProperty> ()
582 return client.InnerChannel.GetProperty<TProperty> ();