|
//*****************************************************************************
// Description.....Null Transport
//
// Author..........Roman Kiss, rkiss@pathcom.com
// Copyright © 2007 ATZ Consulting Inc. (see included license.rtf file)
//
// Date Created: 07/07/07
//
// Date Modified By Description
//-----------------------------------------------------------------------------
// 07/07/07 Roman Kiss Initial Revision
//*****************************************************************************
//
#region Namespaces
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Threading;
#endregion
namespace RKiss.NullChannelLib
{
#region NullRequestContextCollection
public class NullAsyncRequestContextCollection
{
Dictionary<Guid, NullAsyncRequestContext> collection = new Dictionary<Guid,NullAsyncRequestContext>();
public void Add(NullAsyncRequestContext context)
{
lock (collection)
{
collection.Add(context.Id, context);
}
}
public void Close(NullAsyncRequestContext context)
{
lock (collection)
{
if (collection.ContainsKey(context.Id))
{
collection.Remove(context.Id);
}
context.Close();
}
}
public void AbortAll()
{
lock (collection)
{
Dictionary<Guid, NullAsyncRequestContext>.Enumerator en = collection.GetEnumerator();
while (en.MoveNext())
{
en.Current.Value.Abort();
}
collection.Clear();
}
}
}
#endregion
#region NullAsyncRequestContext
public class NullAsyncRequestContext : RequestContext, IAsyncResult
{
#region Private Members
Guid _id;
Message _request = null;
Message _response = null;
Exception _requestException = null;
ManualResetEvent _waitForReply = null;
bool _aborted = false;
bool _replySent = false;
object _thisLock = new object();
CommunicationState _state = CommunicationState.Opened;
TimeSpan _timeout;
AsyncCallback _callback = null;
object _apiState = null;
bool _completedSynchronously = false;
bool _endCalled = false;
#endregion
#region Constructors
public NullAsyncRequestContext(Message message, TimeSpan timeout)
: this(message, timeout, null, null)
{
_waitForReply = new ManualResetEvent(false);
}
public NullAsyncRequestContext(Message message, TimeSpan timeout, AsyncCallback callback, object state)
: base()
{
MessageBuffer buffer = message.CreateBufferedCopy(int.MaxValue);
_request = buffer.CreateMessage();
_id = Guid.NewGuid();
_timeout = timeout;
_callback = callback;
_apiState = state;
}
#endregion
#region Helpers
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
if (_replySent)
this.Close();
else
this.Abort();
}
if (_waitForReply != null)
{
_waitForReply.Close();
_waitForReply = null;
}
}
protected object ThisLock
{
get { return _thisLock; }
}
protected void ThrowIfInvalidReply()
{
if ((_state == CommunicationState.Closed) || (_state == CommunicationState.Closing))
{
if (_aborted)
{
throw new CommunicationObjectAbortedException("RequestContext has been Aborted");
}
throw new ObjectDisposedException(base.GetType().FullName);
}
if (_replySent)
{
throw new InvalidOperationException("Reply has been already sent");
}
}
#endregion
#region Abort
public void Abort(string reason)
{
this.SetRequestException = new Exception(reason);
this.Abort();
}
public void Abort(Exception exception)
{
this.SetRequestException = exception;
this.Abort();
}
public override void Abort()
{
lock (ThisLock)
{
if (_aborted)
return;
_state = CommunicationState.Closed;
_aborted = true;
if (_waitForReply != null)
{
_waitForReply.Set();
}
}
}
#endregion
#region Close
public override void Close(TimeSpan timeout)
{
this.Close();
}
public override void Close()
{
lock (ThisLock)
{
if (_state != CommunicationState.Opened)
return;
_state = CommunicationState.Closed;
}
}
#endregion
#region Reply
public override IAsyncResult BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
{
this.Reply(message, timeout);
return new CompletedAsyncResult(callback, state);
}
public override IAsyncResult BeginReply(Message message, AsyncCallback callback, object state)
{
this.Reply(message);
return new CompletedAsyncResult(callback, state);
}
public override void EndReply(IAsyncResult result)
{
CompletedAsyncResult.End(result);
}
public override void Reply(Message message, TimeSpan timeout)
{
lock (ThisLock)
{
ThrowIfInvalidReply();
if (message != null)
{
MessageBuffer buffer = message.CreateBufferedCopy(int.MaxValue);
_response = buffer.CreateMessage();
}
else
{
_response = null;
}
_replySent = true;
if (_waitForReply != null)
{
_waitForReply.Set();
}
}
if (_callback != null)
{
// in the case of the BeginRequest/EndRequest: call callback for reply is done
_callback(this);
}
}
public override void Reply(Message message)
{
this.Reply(message, _timeout);
}
public Message WaitForReply()
{
return WaitForReply(_timeout);
}
public Message WaitForReply(TimeSpan timeout)
{
bool retval = this.AsyncWaitHandle.WaitOne((int)timeout.TotalMilliseconds, false);
lock (ThisLock)
{
this.Dispose(false);
if (_aborted)
{
if (_requestException != null)
throw _requestException;
else
throw new CommunicationObjectAbortedException("RequestContext aborted");
}
if (retval == false)
{
this.Abort();
throw new CommunicationObjectAbortedException("RequestContext timeout");
}
}
return _response;
}
#endregion
#region IAsyncResult Members
public object AsyncState
{
get { return _apiState; }
}
public WaitHandle AsyncWaitHandle
{
get
{
if (_waitForReply != null)
{
return _waitForReply;
}
lock (ThisLock)
{
if (_waitForReply == null)
{
_waitForReply = new ManualResetEvent(_replySent);
}
}
return _waitForReply;
}
}
public bool CompletedSynchronously
{
get { return _completedSynchronously; }
}
public bool IsCompleted
{
get { return _replySent; }
}
#endregion
#region End
public static Message End(IAsyncResult result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
NullAsyncRequestContext asyncResult = result as NullAsyncRequestContext;
if (asyncResult == null)
{
throw new ArgumentException("Invalid async result.", "result");
}
if (asyncResult._endCalled)
{
throw new InvalidOperationException("Async object already ended.");
}
asyncResult._endCalled = true;
if (asyncResult._replySent == false)
{
// blocking method
asyncResult.WaitForReply();
}
if (asyncResult._requestException != null)
{
throw asyncResult._requestException;
}
return asyncResult._response;
}
#endregion
#region Get Methods
public Guid Id
{
get { return _id; }
}
public Exception SetRequestException
{
set { _requestException = value; }
}
public override Message RequestMessage
{
get
{
if (_requestException != null)
{
throw _requestException;
}
return _request;
}
}
public Message ResponseMessage
{
get { return _response; }
}
#endregion
}
#endregion
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.