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 InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs
310 internal InvokeAsyncCompletedEventArgs (object [] results, Exception error, bool cancelled, object userState)
311 : base (error, cancelled, userState)
316 public object [] Results { get; private set; }
319 protected class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel where T : class
321 ClientBase<T> client;
323 protected ChannelBase (ClientBase<T> client)
325 this.client = client;
329 protected IAsyncResult BeginInvoke (string methodName, object [] args, AsyncCallback callback, object state)
331 throw new NotImplementedException ();
335 protected object EndInvoke (string methodName, object [] args, IAsyncResult result)
337 throw new NotImplementedException ();
340 #region ICommunicationObject
342 IAsyncResult ICommunicationObject.BeginClose (AsyncCallback callback, object state)
344 return client.InnerChannel.BeginClose (callback, state);
347 IAsyncResult ICommunicationObject.BeginClose (TimeSpan timeout, AsyncCallback callback, object state)
349 return client.InnerChannel.BeginClose (timeout, callback, state);
352 void ICommunicationObject.Close ()
354 client.InnerChannel.Close ();
357 void ICommunicationObject.Close (TimeSpan timeout)
359 client.InnerChannel.Close (timeout);
362 IAsyncResult ICommunicationObject.BeginOpen (AsyncCallback callback, object state)
364 return client.InnerChannel.BeginOpen (callback, state);
367 IAsyncResult ICommunicationObject.BeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
369 return client.InnerChannel.BeginOpen (timeout, callback, state);
372 void ICommunicationObject.Open ()
374 client.InnerChannel.Open ();
377 void ICommunicationObject.Open (TimeSpan timeout)
379 client.InnerChannel.Open (timeout);
382 void ICommunicationObject.Abort ()
384 client.InnerChannel.Abort ();
387 void ICommunicationObject.EndClose (IAsyncResult result)
389 client.InnerChannel.EndClose (result);
392 void ICommunicationObject.EndOpen (IAsyncResult result)
394 client.InnerChannel.EndOpen (result);
397 CommunicationState ICommunicationObject.State {
398 get { return client.InnerChannel.State; }
401 event EventHandler ICommunicationObject.Opened {
402 add { client.InnerChannel.Opened += value; }
403 remove { client.InnerChannel.Opened -= value; }
406 event EventHandler ICommunicationObject.Opening {
407 add { client.InnerChannel.Opening += value; }
408 remove { client.InnerChannel.Opening -= value; }
411 event EventHandler ICommunicationObject.Closed {
412 add { client.InnerChannel.Closed += value; }
413 remove { client.InnerChannel.Closed -= value; }
416 event EventHandler ICommunicationObject.Closing {
417 add { client.InnerChannel.Closing += value; }
418 remove { client.InnerChannel.Closing -= value; }
421 event EventHandler ICommunicationObject.Faulted {
422 add { client.InnerChannel.Faulted += value; }
423 remove { client.InnerChannel.Faulted -= value; }
428 #region IClientChannel
430 public bool AllowInitializationUI {
431 get { return client.InnerChannel.AllowInitializationUI; }
432 set { client.InnerChannel.AllowInitializationUI = value; }
435 public bool DidInteractiveInitialization {
436 get { return client.InnerChannel.DidInteractiveInitialization; }
440 get { return client.InnerChannel.Via; }
443 public IAsyncResult BeginDisplayInitializationUI (
444 AsyncCallback callback, object state)
446 return client.InnerChannel.BeginDisplayInitializationUI (callback, state);
449 public void EndDisplayInitializationUI (
452 client.InnerChannel.EndDisplayInitializationUI (result);
455 public void DisplayInitializationUI ()
457 client.InnerChannel.DisplayInitializationUI ();
460 public void Dispose ()
462 client.InnerChannel.Dispose ();
465 public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived {
466 add { client.InnerChannel.UnknownMessageReceived += value; }
467 remove { client.InnerChannel.UnknownMessageReceived -= value; }
472 #region IContextChannel
475 public bool AllowOutputBatching {
476 get { return client.InnerChannel.AllowOutputBatching; }
478 set { client.InnerChannel.AllowOutputBatching = value; }
482 public IInputSession InputSession {
483 get { return client.InnerChannel.InputSession; }
487 public EndpointAddress LocalAddress {
488 get { return client.InnerChannel.LocalAddress; }
492 public TimeSpan OperationTimeout {
493 get { return client.InnerChannel.OperationTimeout; }
494 set { client.InnerChannel.OperationTimeout = value; }
498 public IOutputSession OutputSession {
499 get { return client.InnerChannel.OutputSession; }
503 public EndpointAddress RemoteAddress {
504 get { return client.InnerChannel.RemoteAddress; }
508 public string SessionId {
509 get { return client.InnerChannel.SessionId; }
516 IAsyncResult IRequestChannel.BeginRequest (Message message, AsyncCallback callback, object state)
518 throw new NotImplementedException ();
522 IAsyncResult IRequestChannel.BeginRequest (Message message, TimeSpan timeout, AsyncCallback callback, object state)
524 throw new NotImplementedException ();
528 Message IRequestChannel.EndRequest (IAsyncResult result)
530 throw new NotImplementedException ();
534 Message IRequestChannel.Request (Message message)
536 throw new NotImplementedException ();
540 Message IRequestChannel.Request (Message message, TimeSpan timeout)
542 throw new NotImplementedException ();
546 EndpointAddress IRequestChannel.RemoteAddress {
547 get { throw new NotImplementedException (); }
551 Uri IRequestChannel.Via {
552 get { throw new NotImplementedException (); }
556 IAsyncResult IOutputChannel.BeginSend (Message message, AsyncCallback callback, object state)
558 throw new NotImplementedException ();
562 IAsyncResult IOutputChannel.BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
564 throw new NotImplementedException ();
568 void IOutputChannel.EndSend (IAsyncResult result)
570 throw new NotImplementedException ();
574 void IOutputChannel.Send (Message message)
576 throw new NotImplementedException ();
580 void IOutputChannel.Send (Message message, TimeSpan timeout)
582 throw new NotImplementedException ();
586 IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions {
587 get { return client.InnerChannel.Extensions; }
591 TProperty IChannel.GetProperty<TProperty> ()
593 return client.InnerChannel.GetProperty<TProperty> ();