File: FrameworkFork\System.ServiceModel\System\ServiceModel\ClientBase.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.ComponentModel;
using System.Runtime;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Threading;
 
namespace System.ServiceModel
{
    public abstract class ClientBase<TChannel> : ICommunicationObject, IDisposable
        where TChannel : class
    {
        private TChannel _channel;
        private ChannelFactory<TChannel> _channelFactory;
 
        private object _syncRoot = new object();
 
        private static AsyncCallback s_onAsyncCallCompleted = Fx.ThunkCallback(new AsyncCallback(OnAsyncCallCompleted));
 
        protected ClientBase()
        {
            throw new PlatformNotSupportedException(SRServiceModel.ConfigurationFilesNotSupported);
        }
 
        protected ClientBase(string endpointConfigurationName)
        {
            throw new PlatformNotSupportedException(SRServiceModel.ConfigurationFilesNotSupported);
        }
 
        protected ClientBase(string endpointConfigurationName, string remoteAddress)
        {
            throw new PlatformNotSupportedException(SRServiceModel.ConfigurationFilesNotSupported);
        }
 
        protected ClientBase(string endpointConfigurationName, EndpointAddress remoteAddress)
        {
            throw new PlatformNotSupportedException(SRServiceModel.ConfigurationFilesNotSupported);
        }
 
        protected ClientBase(Binding binding, EndpointAddress remoteAddress)
        {
            if (binding == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
            if (remoteAddress == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
 
            _channelFactory = new ChannelFactory<TChannel>(binding, remoteAddress);
            _channelFactory.TraceOpenAndClose = false;
        }
 
        protected ClientBase(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress)
        {
            if (callbackInstance == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callbackInstance");
            if (binding == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binding");
            if (remoteAddress == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("remoteAddress");
 
            _channelFactory = new DuplexChannelFactory<TChannel>(callbackInstance, binding, remoteAddress);
            _channelFactory.TraceOpenAndClose = false;
        }
 
        protected T GetDefaultValueForInitialization<T>()
        {
            return default(T);
        }
 
        private object ThisLock
        {
            get
            {
                return _syncRoot;
            }
        }
 
        protected TChannel Channel
        {
            get
            {
                // created on demand, so that Mort can modify .Endpoint before calling methods on the client
                if (_channel == null)
                {
                    lock (ThisLock)
                    {
                        if (_channel == null)
                        {
                            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
                            {
                                if (DiagnosticUtility.ShouldUseActivity)
                                {
                                    ServiceModelActivity.Start(activity, string.Format(SRServiceModel.ActivityOpenClientBase, typeof(TChannel).FullName), ActivityType.OpenClient);
                                }
 
                                CreateChannelInternal();
                            }
                        }
                    }
                }
                return _channel;
            }
        }
 
        public ChannelFactory<TChannel> ChannelFactory
        {
            get
            {
                return _channelFactory;
            }
        }
 
        public ClientCredentials ClientCredentials
        {
            get
            {
                return _channelFactory.Credentials;
            }
        }
 
        public CommunicationState State
        {
            get
            {
                IChannel channel = (IChannel)_channel;
                if (channel != null)
                {
                    return channel.State;
                }
                else
                {
                    // we may have failed to create the channel under open, in which case we our factory wouldn't be open
                    return _channelFactory.State;
                }
            }
        }
 
        public IClientChannel InnerChannel
        {
            get
            {
                return (IClientChannel)Channel;
            }
        }
 
        public ServiceEndpoint Endpoint
        {
            get
            {
                return _channelFactory.Endpoint;
            }
        }
 
        public void Open()
        {
            ((ICommunicationObject)this).Open(_channelFactory.InternalOpenTimeout);
        }
 
        public void Abort()
        {
            IChannel channel = (IChannel)_channel;
            if (channel != null)
            {
                channel.Abort();
            }
            _channelFactory.Abort();
        }
 
        public void Close()
        {
            ((ICommunicationObject)this).Close(_channelFactory.InternalCloseTimeout);
        }
 
        private void CreateChannelInternal()
        {
            _channel = CreateChannel();
        }
 
        protected virtual TChannel CreateChannel()
        {
            return _channelFactory.CreateChannel();
        }
 
        void IDisposable.Dispose()
        {
            Close();
        }
 
        void ICommunicationObject.Open(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            _channelFactory.Open(timeoutHelper.RemainingTime());
            InnerChannel.Open(timeoutHelper.RemainingTime());
        }
 
        void ICommunicationObject.Close(TimeSpan timeout)
        {
            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
            {
                if (DiagnosticUtility.ShouldUseActivity)
                {
                    ServiceModelActivity.Start(activity, string.Format(SRServiceModel.ActivityCloseClientBase, typeof(TChannel).FullName), ActivityType.Close);
                }
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
                if (_channel != null)
                {
                    InnerChannel.Close(timeoutHelper.RemainingTime());
                }
 
                _channelFactory.Close(timeoutHelper.RemainingTime());
            }
        }
 
        event EventHandler ICommunicationObject.Closed
        {
            add
            {
                InnerChannel.Closed += value;
            }
            remove
            {
                InnerChannel.Closed -= value;
            }
        }
 
        event EventHandler ICommunicationObject.Closing
        {
            add
            {
                InnerChannel.Closing += value;
            }
            remove
            {
                InnerChannel.Closing -= value;
            }
        }
 
        event EventHandler ICommunicationObject.Faulted
        {
            add
            {
                InnerChannel.Faulted += value;
            }
            remove
            {
                InnerChannel.Faulted -= value;
            }
        }
 
        event EventHandler ICommunicationObject.Opened
        {
            add
            {
                InnerChannel.Opened += value;
            }
            remove
            {
                InnerChannel.Opened -= value;
            }
        }
 
        event EventHandler ICommunicationObject.Opening
        {
            add
            {
                InnerChannel.Opening += value;
            }
            remove
            {
                InnerChannel.Opening -= value;
            }
        }
 
        IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state)
        {
            return ((ICommunicationObject)this).BeginClose(_channelFactory.InternalCloseTimeout, callback, state);
        }
 
        IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new ChainedAsyncResult(timeout, callback, state, BeginChannelClose, EndChannelClose, BeginFactoryClose, EndFactoryClose);
        }
 
        void ICommunicationObject.EndClose(IAsyncResult result)
        {
            ChainedAsyncResult.End(result);
        }
 
        IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state)
        {
            return ((ICommunicationObject)this).BeginOpen(_channelFactory.InternalOpenTimeout, callback, state);
        }
 
        IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new ChainedAsyncResult(timeout, callback, state, BeginFactoryOpen, EndFactoryOpen, BeginChannelOpen, EndChannelOpen);
        }
 
        void ICommunicationObject.EndOpen(IAsyncResult result)
        {
            ChainedAsyncResult.End(result);
        }
 
        //ChainedAsyncResult methods for opening and closing ChannelFactory<T>
 
        internal IAsyncResult BeginFactoryOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return _channelFactory.BeginOpen(timeout, callback, state);
        }
 
        internal void EndFactoryOpen(IAsyncResult result)
        {
            _channelFactory.EndOpen(result);
        }
 
        internal IAsyncResult BeginChannelOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return InnerChannel.BeginOpen(timeout, callback, state);
        }
 
        internal void EndChannelOpen(IAsyncResult result)
        {
            InnerChannel.EndOpen(result);
        }
 
        internal IAsyncResult BeginFactoryClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return _channelFactory.BeginClose(timeout, callback, state);
        }
 
        internal void EndFactoryClose(IAsyncResult result)
        {
            if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
            {
                CompletedAsyncResult.End(result);
            }
            else
            {
                _channelFactory.EndClose(result);
            }
        }
 
        internal IAsyncResult BeginChannelClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            if (_channel != null)
            {
                return InnerChannel.BeginClose(timeout, callback, state);
            }
            else
            {
                return new CompletedAsyncResult(callback, state);
            }
        }
 
        internal void EndChannelClose(IAsyncResult result)
        {
            if (typeof(CompletedAsyncResult).IsAssignableFrom(result.GetType()))
            {
                CompletedAsyncResult.End(result);
            }
            else
            {
                InnerChannel.EndClose(result);
            }
        }
 
        // WARNING: changes in the signature/name of the following delegates must be applied to the 
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
        protected delegate IAsyncResult BeginOperationDelegate(object[] inValues, AsyncCallback asyncCallback, object state);
        protected delegate object[] EndOperationDelegate(IAsyncResult result);
 
        // WARNING: Any changes in the signature/name of the following type and its ctor must be applied to the 
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
        protected class InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs
        {
            private object[] _results;
 
            internal InvokeAsyncCompletedEventArgs(object[] results, Exception error, bool cancelled, object userState)
                : base(error, cancelled, userState)
            {
                _results = results;
            }
 
            public object[] Results
            {
                get
                {
                    return _results;
                }
            }
        }
 
        // WARNING: Any changes in the signature/name of the following method ctor must be applied to the 
        // ClientClassGenerator.cs as well, otherwise the ClientClassGenerator would generate wrong code.
        protected void InvokeAsync(BeginOperationDelegate beginOperationDelegate, object[] inValues,
            EndOperationDelegate endOperationDelegate, SendOrPostCallback operationCompletedCallback, object userState)
        {
            if (beginOperationDelegate == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("beginOperationDelegate");
            }
            if (endOperationDelegate == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endOperationDelegate");
            }
 
            AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(userState);
            AsyncOperationContext context = new AsyncOperationContext(asyncOperation, endOperationDelegate, operationCompletedCallback);
 
            Exception error = null;
            object[] results = null;
            IAsyncResult result = null;
            try
            {
                result = beginOperationDelegate(inValues, s_onAsyncCallCompleted, context);
                if (result.CompletedSynchronously)
                {
                    results = endOperationDelegate(result);
                }
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                error = e;
            }
 
            if (error != null || result.CompletedSynchronously) /* result cannot be null if error == null */
            {
                CompleteAsyncCall(context, results, error);
            }
        }
 
        private static void OnAsyncCallCompleted(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
            {
                return;
            }
 
            AsyncOperationContext context = (AsyncOperationContext)result.AsyncState;
            Exception error = null;
            object[] results = null;
            try
            {
                results = context.EndDelegate(result);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
 
                error = e;
            }
 
            CompleteAsyncCall(context, results, error);
        }
 
        private static void CompleteAsyncCall(AsyncOperationContext context, object[] results, Exception error)
        {
            if (context.CompletionCallback != null)
            {
                InvokeAsyncCompletedEventArgs e = new InvokeAsyncCompletedEventArgs(results, error, false, context.AsyncOperation.UserSuppliedState);
                context.AsyncOperation.PostOperationCompleted(context.CompletionCallback, e);
            }
            else
            {
                context.AsyncOperation.OperationCompleted();
            }
        }
 
        protected class AsyncOperationContext
        {
            private AsyncOperation _asyncOperation;
            private EndOperationDelegate _endDelegate;
            private SendOrPostCallback _completionCallback;
 
            internal AsyncOperationContext(AsyncOperation asyncOperation, EndOperationDelegate endDelegate, SendOrPostCallback completionCallback)
            {
                _asyncOperation = asyncOperation;
                _endDelegate = endDelegate;
                _completionCallback = completionCallback;
            }
 
            internal AsyncOperation AsyncOperation
            {
                get
                {
                    return _asyncOperation;
                }
            }
 
            internal EndOperationDelegate EndDelegate
            {
                get
                {
                    return _endDelegate;
                }
            }
 
            internal SendOrPostCallback CompletionCallback
            {
                get
                {
                    return _completionCallback;
                }
            }
        }
 
        protected class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel, IChannelBaseProxy
            where T : class
        {
            private ServiceChannel _channel;
            private System.ServiceModel.Dispatcher.ImmutableClientRuntime _runtime;
 
            protected ChannelBase(ClientBase<T> client)
            {
                if (client.Endpoint.Address == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRServiceModel.SFxChannelFactoryEndpointAddressUri));
                }
 
                ChannelFactory<T> cf = client._channelFactory;
                cf.EnsureOpened();  // to prevent the NullReferenceException that is thrown if the ChannelFactory is not open when cf.ServiceChannelFactory is accessed.
                _channel = cf.ServiceChannelFactory.CreateServiceChannel(client.Endpoint.Address, client.Endpoint.Address.Uri);
                _channel.InstanceContext = cf.CallbackInstance;
                _runtime = _channel.ClientRuntime.GetRuntime();
            }
 
            protected IAsyncResult BeginInvoke(string methodName, object[] args, AsyncCallback callback, object state)
            {
                object[] inArgs = new object[args.Length + 2];
                Array.Copy(args, inArgs, args.Length);
                inArgs[inArgs.Length - 2] = callback;
                inArgs[inArgs.Length - 1] = state;
 
                MethodCall methodCall = new MethodCall(inArgs);
                ProxyOperationRuntime op = GetOperationByName(methodName);
                object[] ins = op.MapAsyncBeginInputs(methodCall, out callback, out state);
                return _channel.BeginCall(op.Action, op.IsOneWay, op, ins, callback, state);
            }
 
            protected object EndInvoke(string methodName, object[] args, IAsyncResult result)
            {
                object[] inArgs = new object[args.Length + 1];
                Array.Copy(args, inArgs, args.Length);
                inArgs[inArgs.Length - 1] = result;
 
                MethodCall methodCall = new MethodCall(inArgs);
                ProxyOperationRuntime op = GetOperationByName(methodName);
                object[] outs;
                op.MapAsyncEndInputs(methodCall, out result, out outs);
                object ret = _channel.EndCall(op.Action, outs, result);
                object[] retArgs = op.MapAsyncOutputs(methodCall, outs, ref ret);
                if (retArgs != null)
                {
                    Fx.Assert(retArgs.Length == inArgs.Length, "retArgs.Length should be equal to inArgs.Length");
                    Array.Copy(retArgs, args, args.Length);
                }
                return ret;
            }
 
            private System.ServiceModel.Dispatcher.ProxyOperationRuntime GetOperationByName(string methodName)
            {
                ProxyOperationRuntime op = _runtime.GetOperationByName(methodName);
                if (op == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(string.Format(SRServiceModel.SFxMethodNotSupported1, methodName)));
                }
                return op;
            }
 
            bool IClientChannel.AllowInitializationUI
            {
                get { return ((IClientChannel)_channel).AllowInitializationUI; }
                set { ((IClientChannel)_channel).AllowInitializationUI = value; }
            }
 
            bool IClientChannel.DidInteractiveInitialization
            {
                get { return ((IClientChannel)_channel).DidInteractiveInitialization; }
            }
 
            Uri IClientChannel.Via
            {
                get { return ((IClientChannel)_channel).Via; }
            }
 
            event EventHandler<UnknownMessageReceivedEventArgs> IClientChannel.UnknownMessageReceived
            {
                add { ((IClientChannel)_channel).UnknownMessageReceived += value; }
                remove { ((IClientChannel)_channel).UnknownMessageReceived -= value; }
            }
 
            void IClientChannel.DisplayInitializationUI()
            {
                ((IClientChannel)_channel).DisplayInitializationUI();
            }
 
            IAsyncResult IClientChannel.BeginDisplayInitializationUI(AsyncCallback callback, object state)
            {
                return ((IClientChannel)_channel).BeginDisplayInitializationUI(callback, state);
            }
 
            void IClientChannel.EndDisplayInitializationUI(IAsyncResult result)
            {
                ((IClientChannel)_channel).EndDisplayInitializationUI(result);
            }
 
            bool IContextChannel.AllowOutputBatching
            {
                get { return ((IContextChannel)_channel).AllowOutputBatching; }
                set { ((IContextChannel)_channel).AllowOutputBatching = value; }
            }
 
            IInputSession IContextChannel.InputSession
            {
                get { return ((IContextChannel)_channel).InputSession; }
            }
 
            EndpointAddress IContextChannel.LocalAddress
            {
                get { return ((IContextChannel)_channel).LocalAddress; }
            }
 
            TimeSpan IContextChannel.OperationTimeout
            {
                get { return ((IContextChannel)_channel).OperationTimeout; }
                set { ((IContextChannel)_channel).OperationTimeout = value; }
            }
 
            IOutputSession IContextChannel.OutputSession
            {
                get { return ((IContextChannel)_channel).OutputSession; }
            }
 
            EndpointAddress IContextChannel.RemoteAddress
            {
                get { return ((IContextChannel)_channel).RemoteAddress; }
            }
 
            string IContextChannel.SessionId
            {
                get { return ((IContextChannel)_channel).SessionId; }
            }
 
            TProperty IChannel.GetProperty<TProperty>()
            {
                return ((IChannel)_channel).GetProperty<TProperty>();
            }
 
            CommunicationState ICommunicationObject.State
            {
                get { return ((ICommunicationObject)_channel).State; }
            }
 
            event EventHandler ICommunicationObject.Closed
            {
                add { ((ICommunicationObject)_channel).Closed += value; }
                remove { ((ICommunicationObject)_channel).Closed -= value; }
            }
 
            event EventHandler ICommunicationObject.Closing
            {
                add { ((ICommunicationObject)_channel).Closing += value; }
                remove { ((ICommunicationObject)_channel).Closing -= value; }
            }
 
            event EventHandler ICommunicationObject.Faulted
            {
                add { ((ICommunicationObject)_channel).Faulted += value; }
                remove { ((ICommunicationObject)_channel).Faulted -= value; }
            }
 
            event EventHandler ICommunicationObject.Opened
            {
                add { ((ICommunicationObject)_channel).Opened += value; }
                remove { ((ICommunicationObject)_channel).Opened -= value; }
            }
 
            event EventHandler ICommunicationObject.Opening
            {
                add { ((ICommunicationObject)_channel).Opening += value; }
                remove { ((ICommunicationObject)_channel).Opening -= value; }
            }
 
            void ICommunicationObject.Abort()
            {
                ((ICommunicationObject)_channel).Abort();
            }
 
            void ICommunicationObject.Close()
            {
                ((ICommunicationObject)_channel).Close();
            }
 
            void ICommunicationObject.Close(TimeSpan timeout)
            {
                ((ICommunicationObject)_channel).Close(timeout);
            }
 
            IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object state)
            {
                return ((ICommunicationObject)_channel).BeginClose(callback, state);
            }
 
            IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
            {
                return ((ICommunicationObject)_channel).BeginClose(timeout, callback, state);
            }
 
            void ICommunicationObject.EndClose(IAsyncResult result)
            {
                ((ICommunicationObject)_channel).EndClose(result);
            }
 
            void ICommunicationObject.Open()
            {
                ((ICommunicationObject)_channel).Open();
            }
 
            void ICommunicationObject.Open(TimeSpan timeout)
            {
                ((ICommunicationObject)_channel).Open(timeout);
            }
 
            IAsyncResult ICommunicationObject.BeginOpen(AsyncCallback callback, object state)
            {
                return ((ICommunicationObject)_channel).BeginOpen(callback, state);
            }
 
            IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
            {
                return ((ICommunicationObject)_channel).BeginOpen(timeout, callback, state);
            }
 
            void ICommunicationObject.EndOpen(IAsyncResult result)
            {
                ((ICommunicationObject)_channel).EndOpen(result);
            }
 
            IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions
            {
                get { return ((IExtensibleObject<IContextChannel>)_channel).Extensions; }
            }
 
            void IDisposable.Dispose()
            {
                ((IDisposable)_channel).Dispose();
            }
 
            Uri IOutputChannel.Via
            {
                get { return ((IOutputChannel)_channel).Via; }
            }
 
            EndpointAddress IOutputChannel.RemoteAddress
            {
                get { return ((IOutputChannel)_channel).RemoteAddress; }
            }
 
            void IOutputChannel.Send(Message message)
            {
                ((IOutputChannel)_channel).Send(message);
            }
 
            void IOutputChannel.Send(Message message, TimeSpan timeout)
            {
                ((IOutputChannel)_channel).Send(message, timeout);
            }
 
            IAsyncResult IOutputChannel.BeginSend(Message message, AsyncCallback callback, object state)
            {
                return ((IOutputChannel)_channel).BeginSend(message, callback, state);
            }
 
            IAsyncResult IOutputChannel.BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
            {
                return ((IOutputChannel)_channel).BeginSend(message, timeout, callback, state);
            }
 
            void IOutputChannel.EndSend(IAsyncResult result)
            {
                ((IOutputChannel)_channel).EndSend(result);
            }
 
            Uri IRequestChannel.Via
            {
                get { return ((IRequestChannel)_channel).Via; }
            }
 
            EndpointAddress IRequestChannel.RemoteAddress
            {
                get { return ((IRequestChannel)_channel).RemoteAddress; }
            }
 
            Message IRequestChannel.Request(Message message)
            {
                return ((IRequestChannel)_channel).Request(message);
            }
 
            Message IRequestChannel.Request(Message message, TimeSpan timeout)
            {
                return ((IRequestChannel)_channel).Request(message, timeout);
            }
 
            IAsyncResult IRequestChannel.BeginRequest(Message message, AsyncCallback callback, object state)
            {
                return ((IRequestChannel)_channel).BeginRequest(message, callback, state);
            }
 
            IAsyncResult IRequestChannel.BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
            {
                return ((IRequestChannel)_channel).BeginRequest(message, timeout, callback, state);
            }
 
            Message IRequestChannel.EndRequest(IAsyncResult result)
            {
                return ((IRequestChannel)_channel).EndRequest(result);
            }
 
            ServiceChannel IChannelBaseProxy.GetServiceChannel()
            {
                return _channel;
            }
        }
    }
}