2 // CommunicationObject.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005 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
.Reflection
;
30 using System
.ServiceModel
;
31 using System
.Threading
;
33 namespace System
.ServiceModel
.Channels
35 public abstract class CommunicationObject
: ICommunicationObject
38 CommunicationState state
= CommunicationState
.Created
;
39 TimeSpan default_open_timeout
= TimeSpan
.FromMinutes (1), default_close_timeout
= TimeSpan
.FromMinutes (1);
42 protected CommunicationObject ()
43 : this (new object ())
47 protected CommunicationObject (object mutex
)
54 public event EventHandler Closed
;
56 public event EventHandler Closing
;
58 public event EventHandler Faulted
;
60 public event EventHandler Opened
;
62 public event EventHandler Opening
;
68 public CommunicationState State
{
72 protected bool IsDisposed
{
73 get { return state == CommunicationState.Closed; }
76 protected object ThisLock
{
80 protected internal abstract TimeSpan DefaultCloseTimeout { get; }
82 protected internal abstract TimeSpan DefaultOpenTimeout { get; }
90 if (State
!= CommunicationState
.Closed
) {
96 protected void Fault ()
101 public IAsyncResult
BeginClose (AsyncCallback callback
,
104 return BeginClose (default_close_timeout
, callback
, state
);
107 public IAsyncResult
BeginClose (TimeSpan timeout
,
108 AsyncCallback callback
, object state
)
110 if (State
== CommunicationState
.Created
)
111 return new EventHandler (delegate { Abort (); }
).BeginInvoke (null, null, callback
, state
);
113 return OnBeginClose (timeout
, callback
, state
);
116 public IAsyncResult
BeginOpen (AsyncCallback callback
,
119 return BeginOpen (default_open_timeout
, callback
, state
);
122 public IAsyncResult
BeginOpen (TimeSpan timeout
,
123 AsyncCallback callback
, object state
)
126 return OnBeginOpen (timeout
, callback
, state
);
131 Close (default_close_timeout
);
134 public void Close (TimeSpan timeout
)
136 if (State
== CommunicationState
.Created
)
145 public void EndClose (IAsyncResult result
)
147 if (State
== CommunicationState
.Created
|| State
== CommunicationState
.Closed
) {
148 if (!result
.IsCompleted
)
149 result
.AsyncWaitHandle
.WaitOne ();
156 public void EndOpen (IAsyncResult result
)
164 Open (default_open_timeout
);
167 public void Open (TimeSpan timeout
)
174 protected abstract void OnAbort ();
176 protected abstract IAsyncResult
OnBeginClose (TimeSpan timeout
,
177 AsyncCallback callback
, object state
);
179 protected abstract IAsyncResult
OnBeginOpen (TimeSpan timeout
,
180 AsyncCallback callback
, object state
);
182 protected abstract void OnClose (TimeSpan timeout
);
184 void ProcessClosing ()
187 if (State
== CommunicationState
.Faulted
)
188 throw new CommunicationObjectFaultedException ();
190 if (state
!= CommunicationState
.Closing
) {
191 state
= CommunicationState
.Faulted
;
192 throw new InvalidOperationException (String
.Format ("Communication object {0} has an overriden OnClosing method that does not call base OnClosing method (declared in {1} type).", this.GetType (), GetType ().GetMethod ("OnClosing", BindingFlags
.NonPublic
| BindingFlags
.Instance
).DeclaringType
));
197 protected virtual void OnClosing ()
199 state
= CommunicationState
.Closing
;
200 // This means, if this method is overriden, then
201 // Opening event is surpressed.
203 Closing (this, new EventArgs ());
206 void ProcessClosed ()
210 if (state
!= CommunicationState
.Closed
) {
211 state
= CommunicationState
.Faulted
;
212 throw new InvalidOperationException (String
.Format ("Communication object {0} has an overriden OnClosed method that does not call base OnClosed method (declared in {1} type).", this.GetType (), GetType ().GetMethod ("OnClosed", BindingFlags
.NonPublic
| BindingFlags
.Instance
).DeclaringType
));
217 protected virtual void OnClosed ()
219 state
= CommunicationState
.Closed
;
220 // This means, if this method is overriden, then
221 // Closed event is surpressed.
223 Closed (this, new EventArgs ());
226 protected abstract void OnEndClose (IAsyncResult result
);
228 protected abstract void OnEndOpen (IAsyncResult result
);
230 void ProcessFaulted ()
233 if (State
== CommunicationState
.Faulted
)
234 throw new CommunicationObjectFaultedException ();
236 if (state
!= CommunicationState
.Faulted
) {
237 state
= CommunicationState
.Faulted
; // FIXME: am not sure if this makes sense ...
238 throw new InvalidOperationException (String
.Format ("Communication object {0} has an overriden OnFaulted method that does not call base OnFaulted method (declared in {1} type).", this.GetType (), GetType ().GetMethod ("OnFaulted", BindingFlags
.NonPublic
| BindingFlags
.Instance
).DeclaringType
));
243 protected virtual void OnFaulted ()
245 state
= CommunicationState
.Faulted
;
246 // This means, if this method is overriden, then
247 // Faulted event is surpressed.
249 Faulted (this, new EventArgs ());
252 protected abstract void OnOpen (TimeSpan timeout
);
254 void ProcessOpened ()
258 if (state
!= CommunicationState
.Opened
) {
259 state
= CommunicationState
.Faulted
;
260 throw new InvalidOperationException (String
.Format ("Communication object {0} has an overriden OnOpened method that does not call base OnOpened method (declared in {1} type).", this.GetType (), GetType ().GetMethod ("OnOpened", BindingFlags
.NonPublic
| BindingFlags
.Instance
).DeclaringType
));
265 protected virtual void OnOpened ()
267 state
= CommunicationState
.Opened
;
269 Opened (this, new EventArgs ());
272 void ProcessOpening ()
275 ThrowIfDisposedOrImmutable ();
277 if (state
!= CommunicationState
.Opening
) {
278 state
= CommunicationState
.Faulted
;
279 throw new InvalidOperationException (String
.Format ("Communication object {0} has an overriden OnOpening method that does not call base OnOpening method (declared in {1} type).", this.GetType (), GetType ().GetMethod ("OnOpening", BindingFlags
.NonPublic
| BindingFlags
.Instance
).DeclaringType
));
284 protected virtual void OnOpening ()
286 state
= CommunicationState
.Opening
;
287 // This means, if this method is overriden, then
288 // Opening event is surpressed.
290 Opening (this, new EventArgs ());
293 protected void ThrowIfDisposed ()
296 throw new ObjectDisposedException (String
.Format ("This communication object {0} is already disposed.", GetCommunicationObjectType ()));
299 protected void ThrowIfDisposedOrNotOpen ()
302 if (State
== CommunicationState
.Faulted
)
303 throw new CommunicationObjectFaultedException ();
304 if (State
!= CommunicationState
.Opened
)
305 throw new InvalidOperationException (String
.Format ("The communication object {0} must be at opened state.", GetCommunicationObjectType ()));
308 protected void ThrowIfDisposedOrImmutable ()
311 // hmm, according to msdn, Closing is OK here.
313 case CommunicationState
.Faulted
:
314 throw new CommunicationObjectFaultedException ();
315 case CommunicationState
.Opening
:
316 case CommunicationState
.Opened
:
317 throw new InvalidOperationException (String
.Format ("The communication object {0} is not at created state but at {1} state.", GetType (), State
));
321 protected virtual Type
GetCommunicationObjectType ()
329 class SimpleAsyncResult
: IAsyncResult
331 CommunicationState comm_state
;
334 public SimpleAsyncResult (
335 CommunicationState communicationState
,
336 TimeSpan timeout
, AsyncCallback callback
,
339 comm_state
= communicationState
;
340 async_state
= asyncState
;
343 public object AsyncState
{
344 get { return async_state; }
348 public WaitHandle AsyncWaitHandle
{
349 get { throw new NotImplementedException (); }
353 public bool CompletedSynchronously
{
354 get { throw new NotImplementedException (); }
358 public bool IsCompleted
{
359 get { throw new NotImplementedException (); }