Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / XML

NullTransport for WCF

Rate me:
Please Sign up or sign in to vote.
4.91/5 (48 votes)
1 Oct 200712 min read 189.1K   1.7K   121  
This article describes design, implementation and the usage of the custom in-process transport for Microsoft Windows Communication Foundation (WCF) model.
//*****************************************************************************
//    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.Threading;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
#endregion


namespace RKiss.NullChannelLib
{
    public class NullInputChannelListener : ChannelListenerBase<IInputChannel>, IChannel
    {
        #region Private members
        NullTransportBindingElement _element = null;
        BindingContext _context = null;
 
        EndpointAddress _localAddress = null;
        EndpointAddressMessageFilter _filter = null;

        // only one channel is supported
        NullInputChannel _currentChannel = null;
        public AutoResetEvent _waitChannel = new AutoResetEvent(false);
        #endregion

        #region Constructor
        public NullInputChannelListener(NullTransportBindingElement element, BindingContext context)
            : base(context.Binding)
        {
            _element = element;
            _context = context;
            Uri listenUri = new Uri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
            _localAddress = new EndpointAddress(listenUri);
            _filter = new EndpointAddressMessageFilter(_localAddress);
        }
        #endregion

        #region Enqueing
        public void EnqueueItem(object item)
        {
            lock (this.ThisLock)
            {
                if (_currentChannel != null)
                {
                    _currentChannel.Dispatch(item as Message);
                }
            }
        }
        #endregion

        #region Uri
        public override Uri Uri
        {
            get { return _localAddress.Uri; }
        } 
        #endregion

        #region Shutdown
        private void Shutdown()
        {
            lock (this.ThisLock)
            {
                NullListeners.Current.Remove(_filter);
                if (_currentChannel != null)
                {
                    _currentChannel.Abort();
                    _currentChannel = null;
                }
            }
            _waitChannel.Set();
        }
        #endregion

        #region Abort
        protected override void OnAbort()
        {
            this.Shutdown();
        }
        #endregion

        #region Accept
        protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
        {
            this.OnAcceptChannel(timeout);
            return new CompletedAsyncResult(callback, state);
        }
        protected override IInputChannel OnAcceptChannel(TimeSpan timeout)
        {
            if (base.State == CommunicationState.Opened)
            {
                if (_currentChannel != null)
                {
                    // we are supporting only one channel, therefore we have to waiting for next one
                    _waitChannel.WaitOne(int.MaxValue, true);

                    lock (ThisLock)
                    {
                        // re-open channel
                        if (base.State == CommunicationState.Opened && _currentChannel != null && _currentChannel.State == CommunicationState.Closed)
                        {
                            _currentChannel = new NullInputChannel(this, _localAddress);
                            _currentChannel.Closed += new EventHandler(OnCurrentChannelClosed);
                        }
                    }
                }
                else
                {
                    lock (ThisLock)
                    {
                        // open channel at first time
                        _currentChannel = new NullInputChannel(this, _localAddress);
                        _currentChannel.Closed += new EventHandler(OnCurrentChannelClosed);
                        int count = NullListeners.Current.Add(_filter, this);
                    }
                }
            }
            return _currentChannel;
        }
        protected override IInputChannel OnEndAcceptChannel(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
            return _currentChannel;
        }
        #endregion

        #region Close
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            this.OnClose(timeout);
            return new CompletedAsyncResult(callback, state);
        }
        protected override void OnClose(TimeSpan timeout)
        {
            this.Shutdown();
        }
        protected override void OnEndClose(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }
        internal void OnCurrentChannelClosed(object sender, EventArgs e)
        {
            lock (ThisLock)
            {
                if (_currentChannel != null)
                {
                    _currentChannel.Closed -= new EventHandler(OnCurrentChannelClosed);
                }
            }
            _waitChannel.Set();
        }
        #endregion

        #region Open
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            this.OnOpen(timeout);
            return new CompletedAsyncResult(callback, state);
        }
        protected override void OnOpen(TimeSpan timeout)
        {
            // nothing to do
        }
        protected override void OnEndOpen(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }
        #endregion

        #region WaitForChannel - NotImplemented
        protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
        {
            throw new NotImplementedException();
        }

        protected override bool OnEndWaitForChannel(IAsyncResult result)
        {
            throw new NotImplementedException();
        }
        protected override bool OnWaitForChannel(TimeSpan timeout)
        {
            throw new NotImplementedException();
        }
        #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.

License

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


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions