ServiceChannelProxy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / ServiceChannelProxy.cs / 1 / ServiceChannelProxy.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections; 
    using System.ServiceModel.Dispatcher; 
    using System.ServiceModel.Description;
    using System.Collections.Specialized; 
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.ServiceModel.Diagnostics; 
    using System.Reflection;
    using System.Runtime.Remoting.Proxies; 
    using System.Runtime.Remoting; 
    using System.Runtime.Remoting.Messaging;
    using System.Security; 
    using System.Xml;
    using System.Xml.Schema;

    ///  
    /// Critical - accesses a variety of LinkDemanded classes/methods (especially RealProxy)
    ///            caller should protect access to the ServiceChannelProxy instance after construction 
    ///  
    [SecurityCritical(SecurityCriticalScope.Everything)]
    internal sealed class ServiceChannelProxy : RealProxy, IRemotingTypeInfo 
    {
        const String activityIdSlotName = "E2ETrace.ActivityID";
        Type proxiedType;
        Type interfaceType; 
        ServiceChannel serviceChannel;
        MbrObject objectWrapper; 
        ImmutableClientRuntime proxyRuntime; 
        MethodDataCache methodDataCache;
 
        internal ServiceChannelProxy(Type interfaceType, Type proxiedType, MessageDirection direction, ServiceChannel serviceChannel)
            : base(proxiedType)
        {
            if (!MessageDirectionHelper.IsDefined(direction)) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("direction"));
 
            this.interfaceType = interfaceType; 
            this.proxiedType = proxiedType;
            this.serviceChannel = serviceChannel; 
            this.proxyRuntime = serviceChannel.ClientRuntime.GetRuntime();
            this.methodDataCache = new MethodDataCache();

            this.objectWrapper = new MbrObject(this, proxiedType); 
        }
 
        //Workaround is to set the activityid in remoting call's LogicalCallContext 
        static LogicalCallContext SetActivityIdInLogicalCallContext(LogicalCallContext logicalCallContext)
        { 
            logicalCallContext.SetData(activityIdSlotName, DiagnosticTrace.ActivityId);
            return logicalCallContext;
        }
 
        IMethodReturnMessage CreateReturnMessage(object ret, object[] returnArgs, IMethodCallMessage methodCall)
        { 
            if (returnArgs != null) 
            {
                return CreateReturnMessage(ret, returnArgs, returnArgs.Length, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall); 
            }
            else
            {
                return new SingleReturnMessage(ret, methodCall); 
            }
        } 
 
        IMethodReturnMessage CreateReturnMessage(object ret, object[] outArgs, int outArgsCount, LogicalCallContext callCtx, IMethodCallMessage mcm)
        { 
            return new ReturnMessage(ret, outArgs, outArgsCount, callCtx, mcm);
        }

        IMethodReturnMessage CreateReturnMessage(Exception e, IMethodCallMessage mcm) 
        {
            return new ReturnMessage(e, mcm); 
        } 

        MethodData GetMethodData(IMethodCallMessage methodCall) 
        {
            MethodBase method = methodCall.MethodBase;

            MethodData methodData; 
            if (methodDataCache.TryGetMethodData(method, out methodData))
            { 
                return methodData; 
            }
 
            bool canCacheMessageData;

            Type declaringType = method.DeclaringType;
            if (declaringType == typeof(object)) 
            {
                MethodType methodType; 
                if (methodCall.MethodBase == typeof(object).GetMethod("GetType")) 
                {
                    methodType = MethodType.GetType; 
                }
                else
                {
                    methodType = MethodType.Object; 
                }
                canCacheMessageData = true; 
                methodData = new MethodData(method, methodType); 
            }
            else if (declaringType.IsInstanceOfType(this.serviceChannel)) 
            {
                canCacheMessageData = true;
                methodData = new MethodData(method, MethodType.Channel);
            } 
            else
            { 
                ProxyOperationRuntime operation = this.proxyRuntime.GetOperation(method, methodCall.Args, out canCacheMessageData); 

                if (operation == null) 
                {
                    if (this.serviceChannel.Factory != null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupported1, method.Name)));
                    else 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SFxMethodNotSupportedOnCallback1, method.Name)));
                } 
 
                MethodType methodType;
 
                if (operation.IsSyncCall(methodCall))
                {
                    methodType = MethodType.Service;
                } 
                else if (operation.IsBeginCall(methodCall))
                { 
                    methodType = MethodType.BeginService; 
                }
                else 
                {
                    methodType = MethodType.EndService;
                }
 
                methodData = new MethodData(method, methodType, operation);
            } 
 
            if (canCacheMessageData)
            { 
                methodDataCache.SetMethodData(methodData);
            }

            return methodData; 
        }
 
        internal ServiceChannel GetServiceChannel() 
        {
            return this.serviceChannel; 
        }

        public override IMessage Invoke(IMessage message)
        { 
            try
            { 
                IMethodCallMessage methodCall = message as IMethodCallMessage; 

                if (methodCall == null) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxExpectedIMethodCallMessage)));

                MethodData methodData = GetMethodData(methodCall);
 
                switch (methodData.MethodType)
                { 
                    case MethodType.Service: 
                        return InvokeService(methodCall, methodData.Operation);
                    case MethodType.BeginService: 
                        return InvokeBeginService(methodCall, methodData.Operation);
                    case MethodType.EndService:
                        return InvokeEndService(methodCall, methodData.Operation);
                    case MethodType.Channel: 
                        return InvokeChannel(methodCall);
                    case MethodType.GetType: 
                        return InvokeGetType(methodCall); 
                    case MethodType.Object:
                        return InvokeObject(methodCall); 
                    default:
                        DiagnosticUtility.DebugAssert("Invalid proxy method type");
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid proxy method type")));
                } 
            }
#pragma warning suppress 56500 // covered by FxCOP 
            catch (Exception e) 
            {
                if (DiagnosticUtility.IsFatal(e)) 
                {
                    throw;
                }
                return CreateReturnMessage(e, message as IMethodCallMessage); 
            }
        } 
 
        IMethodReturnMessage InvokeChannel(IMethodCallMessage methodCall)
        { 
            string activityName = null;
            ActivityType activityType = ActivityType.Unknown;
            if (DiagnosticUtility.ShouldUseActivity)
            { 
                if (ServiceModelActivity.Current == null ||
                    ServiceModelActivity.Current.ActivityType != ActivityType.Close) 
                { 
                    MethodData methodData = this.GetMethodData(methodCall);
                    if (methodData.MethodBase.DeclaringType == typeof(System.ServiceModel.ICommunicationObject) 
                        && methodData.MethodBase.Name.Equals("Close", StringComparison.Ordinal))
                    {
                        activityName = SR.GetString(SR.ActivityClose, this.serviceChannel.GetType().FullName);
                        activityType = ActivityType.Close; 
                    }
                } 
            } 

            using (ServiceModelActivity activity = string.IsNullOrEmpty(activityName) ? null :ServiceModelActivity.CreateBoundedActivity()) 
            {
                if (DiagnosticUtility.ShouldUseActivity)
                {
                    ServiceModelActivity.Start(activity, activityName, activityType); 
                }
                return ExecuteMessage(this.serviceChannel, methodCall); 
            } 
        }
 
        IMethodReturnMessage InvokeGetType(IMethodCallMessage methodCall)
        {
            return CreateReturnMessage(proxiedType, null, 0, SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext), methodCall);
        } 

        IMethodReturnMessage InvokeObject(IMethodCallMessage methodCall) 
        { 
            return RemotingServices.ExecuteMessage(this.objectWrapper, methodCall);
        } 

        IMethodReturnMessage InvokeBeginService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
        {
            AsyncCallback callback; 
            object asyncState;
            object[] ins = operation.MapAsyncBeginInputs(methodCall, out callback, out asyncState); 
            object ret = this.serviceChannel.BeginCall(operation.Action, operation.IsOneWay, operation, ins, callback, asyncState); 
            return CreateReturnMessage(ret, null, methodCall);
        } 

        IMethodReturnMessage InvokeEndService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
        {
            IAsyncResult result; 
            object[] outs;
            operation.MapAsyncEndInputs(methodCall, out result, out outs); 
            object ret = this.serviceChannel.EndCall(operation.Action, outs, result); 
            object[] returnArgs = operation.MapAsyncOutputs(methodCall, outs, ref ret);
            return CreateReturnMessage(ret, returnArgs, methodCall); 
        }

        IMethodReturnMessage InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
        { 
            object[] outs;
            object[] ins = operation.MapSyncInputs(methodCall, out outs); 
            object ret = this.serviceChannel.Call(operation.Action, operation.IsOneWay, operation, ins, outs); 
            object[] returnArgs = operation.MapSyncOutputs(methodCall, outs, ref ret);
            return CreateReturnMessage(ret, returnArgs, methodCall); 
        }

        IMethodReturnMessage ExecuteMessage(object target, IMethodCallMessage methodCall)
        { 
            MethodBase targetMethod = methodCall.MethodBase;
 
            object[] args = methodCall.Args; 
            object returnValue = null;
            try 
            {
                returnValue = targetMethod.Invoke(target, args);
            }
            catch (TargetInvocationException e) 
            {
                return CreateReturnMessage(e.InnerException, methodCall); 
            } 

            return CreateReturnMessage(returnValue, 
                                       args,
                                       args.Length,
                                       null,
                                       methodCall); 
        }
 
        bool IRemotingTypeInfo.CanCastTo(Type toType, object o) 
        {
            return toType.IsAssignableFrom(proxiedType) || serviceChannel.CanCastTo(toType); 
        }

        string IRemotingTypeInfo.TypeName
        { 
            get { return proxiedType.FullName; }
            set { } 
        } 

        class MethodDataCache 
        {
            MethodData[] methodDatas;

            public MethodDataCache() 
            {
                this.methodDatas = new MethodData[4]; 
            } 

            object ThisLock 
            {
                get { return this; }
            }
 
            public bool TryGetMethodData(MethodBase method, out MethodData methodData)
            { 
                lock (ThisLock) 
                {
                    MethodData[] methodDatas = this.methodDatas; 
                    int index = FindMethod(methodDatas, method);
                    if (index >= 0)
                    {
                        methodData = methodDatas[index]; 
                        return true;
                    } 
                    else 
                    {
                        methodData = new MethodData(); 
                        return false;
                    }
                }
            } 

            static int FindMethod(MethodData[] methodDatas, MethodBase methodToFind) 
            { 
                for (int i = 0; i < methodDatas.Length; i++)
                { 
                    MethodBase method = methodDatas[i].MethodBase;
                    if (method == null)
                    {
                        break; 
                    }
                    if (method == methodToFind) 
                    { 
                        return i;
                    } 
                }
                return -1;
            }
 
            public void SetMethodData(MethodData methodData)
            { 
                lock (ThisLock) 
                {
                    int index = FindMethod(this.methodDatas, methodData.MethodBase); 
                    if (index < 0)
                    {
                        for (int i = 0; i < this.methodDatas.Length; i++)
                        { 
                            if (methodDatas[i].MethodBase == null)
                            { 
                                methodDatas[i] = methodData; 
                                return;
                            } 
                        }
                        MethodData[] newMethodDatas = new MethodData[methodDatas.Length * 2];
                        Array.Copy(methodDatas, newMethodDatas, methodDatas.Length);
                        newMethodDatas[methodDatas.Length] = methodData; 
                        this.methodDatas = newMethodDatas;
                    } 
                } 
            }
        } 

        enum MethodType
        {
            Service, 
            BeginService,
            EndService, 
            Channel, 
            Object,
            GetType, 
        }

        struct MethodData
        { 
            MethodBase methodBase;
            MethodType methodType; 
            ProxyOperationRuntime operation; 

            public MethodData(MethodBase methodBase, MethodType methodType) : this(methodBase, methodType, null) 
            {
            }

            public MethodData(MethodBase methodBase, MethodType methodType, ProxyOperationRuntime operation) 
            {
                this.methodBase = methodBase; 
                this.methodType = methodType; 
                this.operation = operation;
            } 

            public MethodBase MethodBase
            {
                get { return methodBase; } 
            }
 
            public MethodType MethodType 
            {
                get { return methodType; } 
            }

            public ProxyOperationRuntime Operation
            { 
                get { return operation; }
            } 
        } 

        class MbrObject : MarshalByRefObject 
        {
            RealProxy proxy;
            Type targetType;
 
            internal MbrObject(RealProxy proxy, Type targetType)
            { 
                this.proxy = proxy; 
                this.targetType = targetType;
            } 

            public override bool Equals(object obj)
            {
                return Object.ReferenceEquals(obj, this.proxy.GetTransparentProxy()); 
            }
 
            public override string ToString() 
            {
                return this.targetType.ToString(); 
            }

            public override int GetHashCode()
            { 
                return this.proxy.GetHashCode();
            } 
        } 

        class SingleReturnMessage : IMethodReturnMessage 
        {
            IMethodCallMessage methodCall;
            object ret;
            PropertyDictionary properties; 

            public SingleReturnMessage(object ret, IMethodCallMessage methodCall) 
            { 
                this.ret = ret;
                this.methodCall = methodCall; 
                this.properties = new PropertyDictionary();
            }

            public int ArgCount 
            {
                get { return 0; } 
            } 

            public object[] Args 
            {
                get { return EmptyArray.Instance; }
            }
 
            public Exception Exception
            { 
                get { return null; } 
            }
 
            public bool HasVarArgs
            {
                get { return methodCall.HasVarArgs; }
            } 

            public LogicalCallContext LogicalCallContext 
            { 
                get { return SetActivityIdInLogicalCallContext(methodCall.LogicalCallContext); }
            } 

            public MethodBase MethodBase
            {
                get { return methodCall.MethodBase; } 
            }
 
            public string MethodName 
            {
                get { return methodCall.MethodName; } 
            }

            public object MethodSignature
            { 
                get { return methodCall.MethodSignature; }
            } 
 
            public object[] OutArgs
            { 
                get { return EmptyArray.Instance; }
            }

            public int OutArgCount 
            {
                get { return 0; } 
            } 

            public IDictionary Properties 
            {
                get { return properties; }
            }
 
            public object ReturnValue
            { 
                get { return ret; } 
            }
 
            public string TypeName
            {
                get { return methodCall.TypeName; }
            } 

            public string Uri 
            { 
                get { return null; }
            } 

            public object GetArg(int index)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index")); 
            }
 
            public string GetArgName(int index) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index")); 
            }

            public object GetOutArg(int index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
            } 
 
            public string GetOutArgName(int index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
            }

            class PropertyDictionary : IDictionary 
            {
                ListDictionary properties; 
 
                public object this[object key]
                { 
                    get { return Properties[key]; }
                    set { Properties[key] = value; }
                }
 
                public int Count
                { 
                    get { return Properties.Count; } 
                }
 
                public bool IsFixedSize
                {
                    get { return false; }
                } 

                public bool IsReadOnly 
                { 
                    get { return false; }
                } 

                public bool IsSynchronized
                {
                    get { return false; } 
                }
 
                public ICollection Keys 
                {
                    get { return Properties.Keys; } 
                }

                ListDictionary Properties
                { 
                    get
                    { 
                        if (properties == null) 
                        {
                            properties = new ListDictionary(); 
                        }
                        return properties;
                    }
                } 

                public ICollection Values 
                { 
                    get { return Properties.Values; }
                } 

                public object SyncRoot
                {
                    get { return null; } 
                }
 
                public void Add(object key, object value) 
                {
                    Properties.Add(key, value); 
                }

                public void Clear()
                { 
                    Properties.Clear();
                } 
 
                public bool Contains(object key)
                { 
                    return Properties.Contains(key);
                }

                public void CopyTo(Array array, int index) 
                {
                    Properties.CopyTo(array, index); 
                } 

                public IDictionaryEnumerator GetEnumerator() 
                {
                    if (properties == null)
                    {
                        return EmptyEnumerator.Instance; 
                    }
                    else 
                    { 
                        return properties.GetEnumerator();
                    } 
                }

                IEnumerator IEnumerable.GetEnumerator()
                { 
                    return ((IEnumerable)Properties).GetEnumerator();
                } 
 
                public void Remove(object key)
                { 
                    Properties.Remove(key);
                }

                class EmptyEnumerator : IDictionaryEnumerator 
                {
                    static EmptyEnumerator instance = new EmptyEnumerator(); 
 
                    EmptyEnumerator()
                    { 
                    }

                    public static EmptyEnumerator Instance
                    { 
                        get { return instance; }
                    } 
 
                    public bool MoveNext()
                    { 
                        return false;
                    }

                    public Object Current 
                    {
                        get 
                        { 
#pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty))); 
                        }
                    }

                    public void Reset() 
                    {
                    } 
 
                    public Object Key
                    { 
                        get
                        {
#pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty))); 
                        }
                    } 
 
                    public Object Value
                    { 
                        get
                        {
#pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty))); 
                        }
                    } 
 
                    public DictionaryEntry Entry
                    { 
                        get
                        {
#pragma warning suppress 56503 // [....], IEnumerator guidelines, Current throws exception before calling MoveNext
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDictionaryIsEmpty))); 
                        }
                    } 
                } 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK