XmlSerializerOperationBehavior.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 / Description / XmlSerializerOperationBehavior.cs / 3 / XmlSerializerOperationBehavior.cs

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

namespace System.ServiceModel.Description 
{
    using System; 
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Dispatcher;
    using System.Reflection; 
    using System.Xml;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Xml.Serialization; 
    using System.ServiceModel;
    using System.Collections; 
    using System.Diagnostics; 
    using System.Collections.ObjectModel;
    using System.Security; 

    public class XmlSerializerOperationBehavior : IOperationBehavior, IWsdlExportExtension
    {
        readonly Reflector.OperationReflector reflector; 
        readonly bool builtInOperationBehavior;
 
        public XmlSerializerOperationBehavior(OperationDescription operation) 
            : this (operation, null)
        { 
        }

        public XmlSerializerOperationBehavior(OperationDescription operation, XmlSerializerFormatAttribute attribute)
        { 
            if (operation == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operation"); 
#pragma warning suppress 56506 // Declaring contract cannot be null 
            Reflector parentReflector = new Reflector(operation.DeclaringContract.Namespace, operation.DeclaringContract.ContractType);
#pragma warning suppress 56506 // parentReflector cannot be null 
            this.reflector = parentReflector.ReflectOperation(operation, attribute ?? new XmlSerializerFormatAttribute());
        }

        internal XmlSerializerOperationBehavior(OperationDescription operation, XmlSerializerFormatAttribute attribute, Reflector parentReflector) 
            : this (operation, attribute)
        { 
            // used by System.ServiceModel.Web 
            this.reflector = parentReflector.ReflectOperation(operation, attribute ?? new XmlSerializerFormatAttribute());
        } 

        XmlSerializerOperationBehavior(Reflector.OperationReflector reflector, bool builtInOperationBehavior)
        {
            DiagnosticUtility.DebugAssert(reflector != null, ""); 
            this.reflector = reflector;
            this.builtInOperationBehavior = builtInOperationBehavior; 
        } 

        internal Reflector.OperationReflector OperationReflector 
        {
            get { return this.reflector; }
        }
 
        internal bool IsBuiltInOperationBehavior
        { 
            get { return this.builtInOperationBehavior; } 
        }
 
        public XmlSerializerFormatAttribute XmlSerializerFormatAttribute
        {
            get
            { 
                return this.reflector.Attribute;
            } 
        } 

        internal static XmlSerializerOperationFormatter CreateOperationFormatter(OperationDescription operation) 
        {
            return new XmlSerializerOperationBehavior(operation).CreateFormatter();
        }
 
        internal static XmlSerializerOperationFormatter CreateOperationFormatter(OperationDescription operation, XmlSerializerFormatAttribute attr)
        { 
            return new XmlSerializerOperationBehavior(operation, attr).CreateFormatter(); 
        }
 
        internal static void AddBehaviors(ContractDescription contract)
        {
            AddBehaviors(contract, false);
        } 

        internal static void AddBuiltInBehaviors(ContractDescription contract) 
        { 
            AddBehaviors(contract, true);
        } 

        static void AddBehaviors(ContractDescription contract, bool builtInOperationBehavior)
        {
            Reflector reflector = new Reflector(contract.Namespace, contract.ContractType); 

            foreach (OperationDescription operation in contract.Operations) 
            { 

                Reflector.OperationReflector operationReflector = reflector.ReflectOperation(operation); 
                if (operationReflector != null)
                {
                    bool isInherited = operation.DeclaringContract != contract;
                    if (!isInherited) 
                    {
                        operation.Behaviors.Add(new XmlSerializerOperationBehavior(operationReflector, builtInOperationBehavior)); 
                        operation.Behaviors.Add(new XmlSerializerOperationGenerator(new XmlSerializerImportOptions())); 
                    }
                } 
            }
        }

        internal XmlSerializerOperationFormatter CreateFormatter() 
        {
            return new XmlSerializerOperationFormatter(reflector.Operation, reflector.Attribute, reflector.Request, reflector.Reply); 
        } 

        XmlSerializerFaultFormatter CreateFaultFormatter(SynchronizedCollection faultContractInfos) 
        {
            return new XmlSerializerFaultFormatter(faultContractInfos, reflector.XmlSerializerFaultContractInfos);
        }
 
        void IOperationBehavior.Validate(OperationDescription description)
        { 
        } 

        void IOperationBehavior.AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) 
        {
        }

        void IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch) 
        {
            if (description == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description"); 

            if (dispatch == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dispatch");

            if (dispatch.Formatter != null)
                return; 

            dispatch.Formatter = (IDispatchMessageFormatter)CreateFormatter(); 
            dispatch.DeserializeRequest = reflector.RequestRequiresSerialization; 
            dispatch.SerializeReply = reflector.ReplyRequiresSerialization;
 
            if (reflector.Attribute.SupportFaults && !dispatch.IsFaultFormatterSetExplicit)
                dispatch.FaultFormatter = (IDispatchFaultFormatter)CreateFaultFormatter(dispatch.FaultContractInfos);
        }
 
        void IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
        { 
            if (description == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
 
            if (proxy == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("proxy");

            if (proxy.Formatter != null) 
                return;
 
            proxy.Formatter = (IClientMessageFormatter)CreateFormatter(); 
            proxy.SerializeRequest = reflector.RequestRequiresSerialization;
            proxy.DeserializeReply = reflector.ReplyRequiresSerialization; 

            if (reflector.Attribute.SupportFaults && !proxy.IsFaultFormatterSetExplicit)
                proxy.FaultFormatter = (IClientFaultFormatter)CreateFaultFormatter(proxy.FaultContractInfos);
        } 

        void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext endpointContext) 
        { 
            if (exporter == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exporter"); 
            if (endpointContext == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointContext");

            MessageContractExporter.ExportMessageBinding(exporter, endpointContext, typeof(XmlSerializerMessageContractExporter), this.reflector.Operation); 
        }
 
        void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext) 
        {
            if (exporter == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exporter");
            if (contractContext == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractContext");
            new XmlSerializerMessageContractExporter(exporter, contractContext, this.reflector.Operation, this).ExportMessageContract(); 
        }
 
        public Collection GetXmlMappings() 
        {
            Collection mappings = new Collection(); 
            if (OperationReflector.Request != null && OperationReflector.Request.HeadersMapping != null)
                mappings.Add(OperationReflector.Request.HeadersMapping);
            if (OperationReflector.Request != null && OperationReflector.Request.BodyMapping != null)
                mappings.Add(OperationReflector.Request.BodyMapping); 
            if (OperationReflector.Reply != null && OperationReflector.Reply.HeadersMapping != null)
                mappings.Add(OperationReflector.Reply.HeadersMapping); 
            if (OperationReflector.Reply != null && OperationReflector.Reply.BodyMapping != null) 
                mappings.Add(OperationReflector.Reply.BodyMapping);
            return mappings; 
        }

        // helper for reflecting operations
        internal class Reflector 
        {
            readonly XmlSerializerImporter importer; 
            readonly SerializerGenerationContext generation; 
            Collection operationReflectors = new Collection();
            object thisLock = new object(); 

            internal Reflector(string defaultNs, Type type)
            {
                this.importer = new XmlSerializerImporter(defaultNs); 
                this.generation = new SerializerGenerationContext(type);
            } 
 
            internal void EnsureMessageInfos()
            { 
                lock (this.thisLock)
                {
                    foreach (OperationReflector operationReflector in operationReflectors)
                    { 
                        operationReflector.EnsureMessageInfos();
                    } 
                } 
            }
 

            static XmlSerializerFormatAttribute FindAttribute(OperationDescription operation)
            {
                Type contractType = operation.DeclaringContract != null ? operation.DeclaringContract.ContractType : null; 
                XmlSerializerFormatAttribute contractFormatAttribute = contractType != null ? TypeLoader.GetFormattingAttribute(contractType, null) as XmlSerializerFormatAttribute : null;
                return TypeLoader.GetFormattingAttribute(operation.OperationMethod, contractFormatAttribute) as XmlSerializerFormatAttribute; 
            } 

            // auto-reflects the operation, returning null if no attribute was found or inherited 
            internal OperationReflector ReflectOperation(OperationDescription operation)
            {
                XmlSerializerFormatAttribute attr = FindAttribute(operation);
                if (attr == null) 
                    return null;
 
                return ReflectOperation(operation, attr); 
            }
 
            // overrides the auto-reflection with an attribute
            internal OperationReflector ReflectOperation(OperationDescription operation, XmlSerializerFormatAttribute attrOverride)
            {
                OperationReflector operationReflector = new OperationReflector(this, operation, attrOverride, true/*reflectOnDemand*/); 
                operationReflectors.Add(operationReflector);
 
                return operationReflector; 
            }
 
            internal class OperationReflector
            {
                readonly Reflector parent;
 
                internal readonly OperationDescription Operation;
                internal readonly XmlSerializerFormatAttribute Attribute; 
 
                internal readonly bool IsEncoded;
                internal readonly bool IsRpc; 
                internal readonly bool IsOneWay;
                internal readonly bool RequestRequiresSerialization;
                internal readonly bool ReplyRequiresSerialization;
 
                readonly string keyBase;
 
                MessageInfo request; 
                MessageInfo reply;
                SynchronizedCollection xmlSerializerFaultContractInfos; 

                internal OperationReflector(Reflector parent, OperationDescription operation, XmlSerializerFormatAttribute attr, bool reflectOnDemand)
                {
                    DiagnosticUtility.DebugAssert(parent != null, ""); 
                    DiagnosticUtility.DebugAssert(operation != null, "");
                    DiagnosticUtility.DebugAssert(attr != null, ""); 
 
                    OperationFormatter.Validate(operation, attr.Style == OperationFormatStyle.Rpc, attr.IsEncoded);
 
                    this.parent = parent;

                    this.Operation = operation;
                    this.Attribute = attr; 

                    this.IsEncoded = attr.IsEncoded; 
                    this.IsRpc = (attr.Style == OperationFormatStyle.Rpc); 
                    this.IsOneWay = operation.Messages.Count == 1;
 
                    this.RequestRequiresSerialization = !operation.Messages[0].IsUntypedMessage;
                    this.ReplyRequiresSerialization = !this.IsOneWay && !operation.Messages[1].IsUntypedMessage;

                    MethodInfo methodInfo = operation.OperationMethod; 
                    if (methodInfo == null)
                        keyBase = string.Empty; 
                    else 
                        keyBase = methodInfo.DeclaringType.FullName + ":" + methodInfo.ToString();
 
                    foreach (MessageDescription message in operation.Messages)
                        foreach (MessageHeaderDescription header in message.Headers)
                            SetUnknownHeaderInDescription(header);
                    if (!reflectOnDemand) 
                    {
                        this.EnsureMessageInfos(); 
                    } 
                }
 
                private void SetUnknownHeaderInDescription(MessageHeaderDescription header)
                {
                    if (this.IsEncoded) //XmlAnyElementAttribute does not apply
                        return; 
                    XmlAttributes xmlAttributes =  new XmlAttributes(header.AdditionalAttributesProvider);
                    foreach (XmlAnyElementAttribute anyElement in xmlAttributes.XmlAnyElements) 
                    { 
                        if (String.IsNullOrEmpty(anyElement.Name))
                        { 
                            header.IsUnknownHeaderCollection = true;
                        }
                    }
 
                }
 
                string ContractName 
                {
                    get { return this.Operation.DeclaringContract.Name; } 
                }

                string ContractNamespace
                { 
                    get { return this.Operation.DeclaringContract.Namespace; }
                } 
 
                internal MessageInfo Request
                { 
                    get
                    {
                        parent.EnsureMessageInfos();
                        return this.request; 
                    }
                } 
 
                internal MessageInfo Reply
                { 
                    get
                    {
                        parent.EnsureMessageInfos();
                        return this.reply; 
                    }
                } 
 
                internal SynchronizedCollection XmlSerializerFaultContractInfos
                { 
                    get
                    {
                        parent.EnsureMessageInfos();
                        return this.xmlSerializerFaultContractInfos; 
                    }
                } 
 
                internal void EnsureMessageInfos()
                { 
                    if (this.request == null)
                    {
                        foreach (Type knownType in Operation.KnownTypes)
                        { 
                            if (knownType == null)
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxKnownTypeNull, Operation.Name))); 
                            parent.importer.IncludeType(knownType, IsEncoded); 
                        }
                        this.request = CreateMessageInfo(this.Operation.Messages[0], ":Request"); 
                        if (this.request != null && this.IsRpc && this.Operation.IsValidateRpcWrapperName && this.request.BodyMapping.XsdElementName != this.Operation.Name)
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageBodyPartNameInvalid, Operation.Name, this.Operation.Messages[0].MessageName, request.BodyMapping.XsdElementName, this.Operation.Name)));
                        if (!this.IsOneWay)
                        { 
                            this.reply = CreateMessageInfo(this.Operation.Messages[1], ":Response");
                            XmlName responseName = TypeLoader.GetBodyWrapperResponseName(this.Operation.Name); 
                            if (this.reply != null && this.IsRpc && this.Operation.IsValidateRpcWrapperName && this.reply.BodyMapping.XsdElementName != responseName.EncodedName) 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageBodyPartNameInvalid, Operation.Name, this.Operation.Messages[1].MessageName, reply.BodyMapping.XsdElementName, responseName.EncodedName)));
                        } 
                        if (this.Attribute.SupportFaults)
                        {
                            GenerateXmlSerializerFaultContractInfos();
                        } 
                    }
                } 
 
                void GenerateXmlSerializerFaultContractInfos()
                { 
                    SynchronizedCollection faultInfos = new SynchronizedCollection();
                    for (int i = 0; i < this.Operation.Faults.Count; i++)
                    {
                        FaultDescription fault = this.Operation.Faults[i]; 
                        FaultContractInfo faultContractInfo = new FaultContractInfo(fault.Action, fault.DetailType, fault.ElementName, fault.Namespace, this.Operation.KnownTypes);
 
                        XmlQualifiedName elementName; 
                        XmlMembersMapping xmlMembersMapping = this.ImportFaultElement(fault, out elementName);
 
                        SerializerStub serializerStub = parent.generation.AddSerializer(xmlMembersMapping);
                        faultInfos.Add(new XmlSerializerFaultContractInfo(faultContractInfo, serializerStub, elementName));
                    }
                    this.xmlSerializerFaultContractInfos = faultInfos; 
                }
 
                MessageInfo CreateMessageInfo(MessageDescription message, string key) 
                {
                    if (message.IsUntypedMessage) 
                        return null;
                    MessageInfo info = new MessageInfo();
                    if (message.IsTypedMessage)
                        key = message.MessageType.FullName + ":" + IsEncoded + ":" + IsRpc; 
                    XmlMembersMapping headersMapping = LoadHeadersMapping(message, key + ":Headers");
                    info.SetHeaders(parent.generation.AddSerializer(headersMapping)); 
                    MessagePartDescriptionCollection rpcEncodedTypedMessgeBodyParts; 
                    info.SetBody(parent.generation.AddSerializer(LoadBodyMapping(message, key, out rpcEncodedTypedMessgeBodyParts)), rpcEncodedTypedMessgeBodyParts);
                    CreateHeaderDescriptionTable(message, info, headersMapping); 
                    return info;
                }

                private void CreateHeaderDescriptionTable(MessageDescription message, MessageInfo info, XmlMembersMapping headersMapping) 
                {
                    int headerNameIndex = 0; 
                    OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable = new OperationFormatter.MessageHeaderDescriptionTable(); 
                    info.SetHeaderDescriptionTable(headerDescriptionTable);
                    foreach (MessageHeaderDescription header in message.Headers) 
                    {
                        if (header.IsUnknownHeaderCollection)
                            info.SetUnknownHeaderDescription(header);
                        else if (headersMapping != null) 
                        {
                            XmlMemberMapping memberMapping = headersMapping[headerNameIndex++]; 
                            string headerName, headerNs; 
                            if (IsEncoded)
                            { 
                                headerName = memberMapping.TypeName;
                                headerNs = memberMapping.TypeNamespace;
                            }
                            else 
                            {
                                headerName = memberMapping.XsdElementName; 
                                headerNs = memberMapping.Namespace; 
                            }
                            if (headerName != header.Name) 
                            {
                                if (message.MessageType != null)
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNameMismatchInMessageContract, message.MessageType, header.MemberInfo.Name, header.Name, headerName)));
                                else 
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNameMismatchInOperation, this.Operation.Name, this.Operation.DeclaringContract.Name, this.Operation.DeclaringContract.Namespace, header.Name, headerName)));
                            } 
                            if (headerNs != header.Namespace) 
                            {
                                if (message.MessageType != null) 
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNamespaceMismatchInMessageContract, message.MessageType, header.MemberInfo.Name, header.Namespace, headerNs)));
                                else
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNamespaceMismatchInOperation, this.Operation.Name, this.Operation.DeclaringContract.Name, this.Operation.DeclaringContract.Namespace, header.Namespace, headerNs)));
                            } 

                            headerDescriptionTable.Add(headerName, headerNs, header); 
                        } 
                    }
                } 

                XmlMembersMapping LoadBodyMapping(MessageDescription message, string mappingKey, out MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts)
                {
                    MessagePartDescription returnPart; 
                    string wrapperName, wrapperNs;
                    MessagePartDescriptionCollection bodyParts; 
                    if (IsEncoded && message.IsTypedMessage && message.Body.WrapperName == null) 
                    {
                        MessagePartDescription wrapperPart = GetWrapperPart(message); 
                        returnPart = null;
                        rpcEncodedTypedMessageBodyParts = bodyParts = GetWrappedParts(wrapperPart);
                        wrapperName = wrapperPart.Name;
                        wrapperNs = wrapperPart.Namespace; 
                    }
                    else 
                    { 
                        rpcEncodedTypedMessageBodyParts = null;
                        returnPart = OperationFormatter.IsValidReturnValue(message.Body.ReturnValue) ? message.Body.ReturnValue : null; 
                        bodyParts = message.Body.Parts;
                        wrapperName = message.Body.WrapperName;
                        wrapperNs = message.Body.WrapperNamespace;
                    } 
                    bool isWrapped = (wrapperName != null);
                    bool hasReturnValue = returnPart != null; 
                    int paramCount = bodyParts.Count + (hasReturnValue ? 1 : 0); 
                    if (paramCount == 0 && !isWrapped) // no need to create serializer
                    { 
                        return null;
                    }

                    XmlReflectionMember[] members = new XmlReflectionMember[paramCount]; 
                    int paramIndex = 0;
                    if (hasReturnValue) 
                        members[paramIndex++] = XmlSerializerHelper.GetXmlReflectionMember(returnPart, IsRpc, IsEncoded, isWrapped); 

                    for (int i = 0; i < bodyParts.Count; i++) 
                        members[paramIndex++] = XmlSerializerHelper.GetXmlReflectionMember(bodyParts[i], IsRpc, IsEncoded, isWrapped);

                    if (!isWrapped)
                        wrapperNs = ContractNamespace; 
                    return ImportMembersMapping(wrapperName, wrapperNs, members, isWrapped, IsRpc, mappingKey);
                } 
 
                private MessagePartDescription GetWrapperPart(MessageDescription message)
                { 
                    if (message.Body.Parts.Count != 1)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageMustHaveASingleBody, Operation.Name, message.MessageName)));
                    MessagePartDescription bodyPart = message.Body.Parts[0];
                    Type bodyObjectType = bodyPart.Type; 
                    if (bodyObjectType.BaseType != null && bodyObjectType.BaseType != typeof(object))
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInherited, bodyObjectType.FullName))); 
                    if (typeof(IEnumerable).IsAssignableFrom(bodyObjectType)) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInterface, bodyObjectType.FullName, typeof(IEnumerable).FullName)));
                    if (typeof(IXmlSerializable).IsAssignableFrom(bodyObjectType)) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInterface, bodyObjectType.FullName, typeof(IXmlSerializable).FullName)));
                    return bodyPart;
                }
 
                private MessagePartDescriptionCollection GetWrappedParts(MessagePartDescription bodyPart)
                { 
                    Type bodyObjectType =  bodyPart.Type; 
                    MessagePartDescriptionCollection partList = new MessagePartDescriptionCollection();
                    foreach (MemberInfo member in bodyObjectType.GetMembers(BindingFlags.Instance | BindingFlags.Public)) 
                    {
                        if ((member.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0)
                            continue;
                        if (member.IsDefined(typeof(SoapIgnoreAttribute), false/*inherit*/)) 
                            continue;
                        XmlName xmlName = new XmlName(member.Name); 
                        MessagePartDescription part = new MessagePartDescription(xmlName.EncodedName, string.Empty); 
                        part.AdditionalAttributesProvider = part.MemberInfo = member;
                        part.Index = part.SerializationPosition = partList.Count; 
                        part.Type = (member.MemberType == MemberTypes.Property)?((PropertyInfo)member).PropertyType:((FieldInfo)member).FieldType;
                        if (bodyPart.HasProtectionLevel)
                            part.ProtectionLevel = bodyPart.ProtectionLevel;
                        partList.Add(part); 
                    }
                    return partList; 
                } 

                XmlMembersMapping LoadHeadersMapping(MessageDescription message, string mappingKey) 
                {
                    int headerCount = message.Headers.Count;

                    if (headerCount == 0) 
                        return null;
                    if (IsEncoded) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeadersAreNotSupportedInEncoded, message.MessageName))); 

                    int unknownHeaderCount = 0, headerIndex = 0; 
                    XmlReflectionMember[] members = new XmlReflectionMember[headerCount];
                    for (int i = 0; i < headerCount; i++)
                    {
                        MessageHeaderDescription header = message.Headers[i]; 
                        if (!header.IsUnknownHeaderCollection)
                        { 
                            members[headerIndex++] = XmlSerializerHelper.GetXmlReflectionMember(header, false/*isRpc*/, IsEncoded, false/*isWrapped*/); 
                        }
                        else 
                        {
                            unknownHeaderCount++;
                        }
                    } 

                    if (unknownHeaderCount == headerCount) 
                    { 
                        return null;
                    } 

                    if (unknownHeaderCount > 0)
                    {
                        XmlReflectionMember[] newMembers = new XmlReflectionMember[headerCount - unknownHeaderCount]; 
                        Array.Copy(members, newMembers, newMembers.Length);
                        members = newMembers; 
                    } 

                    return ImportMembersMapping(ContractName, ContractNamespace, members, false /*isWrapped*/, false /*isRpc*/, mappingKey); 
                }

                internal XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, string mappingKey)
                { 
                    string key = mappingKey.StartsWith(":", StringComparison.Ordinal) ? keyBase + mappingKey : mappingKey;
                    return this.parent.importer.ImportMembersMapping(new XmlName(elementName, true /*isEncoded*/), ns, members, hasWrapperElement, rpc, this.IsEncoded, key); 
                } 

                internal XmlMembersMapping ImportFaultElement(FaultDescription fault, out XmlQualifiedName elementName) 
                {
                    // the number of reflection members is always 1 because there is only one fault detail type
                    XmlReflectionMember[] members = new XmlReflectionMember[1];
 
                    XmlName faultElementName = fault.ElementName;
                    string faultNamespace = fault.Namespace; 
                    if (faultElementName == null) 
                    {
                        XmlTypeMapping mapping = this.parent.importer.ImportTypeMapping(fault.DetailType, this.IsEncoded); 
                        faultElementName = new XmlName(mapping.ElementName, this.IsEncoded);
                        faultNamespace = mapping.Namespace;
                        if (faultElementName == null)
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxFaultTypeAnonymous, this.Operation.Name, fault.DetailType.FullName))); 
                    }
 
                    elementName = new XmlQualifiedName(faultElementName.DecodedName, faultNamespace); 

                    members[0] = XmlSerializerHelper.GetXmlReflectionMember(null /*memberName*/, faultElementName, faultNamespace, fault.DetailType, 
                        null /*additionalAttributesProvider*/, false /*isMultiple*/, this.IsEncoded, false /*isWrapped*/);

                    string mappingKey = "fault:" + faultElementName.DecodedName + ":" + faultNamespace;
                    return ImportMembersMapping(faultElementName.EncodedName, faultNamespace, members, false /*hasWrapperElement*/, this.IsRpc, mappingKey); 
                }
            } 
 
            class XmlSerializerImporter
            { 
                readonly string defaultNs;
                XmlReflectionImporter xmlImporter;
                SoapReflectionImporter soapImporter;
                Dictionary xmlMappings; 

                internal XmlSerializerImporter(string defaultNs) 
                { 
                    this.defaultNs = defaultNs;
                    this.xmlImporter = null; 
                    this.soapImporter = null;
                }

                SoapReflectionImporter SoapImporter 
                {
                    get 
                    { 
                        if (this.soapImporter == null)
                        { 
                            this.soapImporter = new SoapReflectionImporter(NamingHelper.CombineUriStrings(defaultNs, "encoded"));
                        }
                        return this.soapImporter;
                    } 
                }
 
                XmlReflectionImporter XmlImporter 
                {
                    get 
                    {
                        if (this.xmlImporter == null)
                        {
                            this.xmlImporter = new XmlReflectionImporter(defaultNs); 
                        }
                        return this.xmlImporter; 
                    } 
                }
 
                Dictionary XmlMappings
                {
                    get
                    { 
                        if (this.xmlMappings == null)
                        { 
                            this.xmlMappings = new Dictionary(); 
                        }
                        return this.xmlMappings; 
                    }
                }

                internal XmlMembersMapping ImportMembersMapping(XmlName elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, bool isEncoded, string mappingKey) 
                {
                    XmlMembersMapping mapping; 
                    string mappingName = elementName.DecodedName; 
                    if (XmlMappings.TryGetValue(mappingKey, out mapping))
                    { 
                        return mapping;
                    }

                    if (isEncoded) 
                        mapping = this.SoapImporter.ImportMembersMapping(mappingName, ns, members, hasWrapperElement, rpc);
                    else 
                        mapping = this.XmlImporter.ImportMembersMapping(mappingName, ns, members, hasWrapperElement, rpc); 

                    mapping.SetKey(mappingKey); 
                    XmlMappings.Add(mappingKey, mapping);
                    return mapping;
                }
 
                internal XmlTypeMapping ImportTypeMapping(Type type, bool isEncoded)
                { 
                    if (isEncoded) 
                        return this.SoapImporter.ImportTypeMapping(type);
                    else 
                        return this.XmlImporter.ImportTypeMapping(type);
                }

                internal void IncludeType(Type knownType, bool isEncoded) 
                {
                    if (isEncoded) 
                        this.SoapImporter.IncludeType(knownType); 
                    else
                        this.XmlImporter.IncludeType(knownType); 
                }
            }

            internal class SerializerGenerationContext 
            {
                List Mappings = new List(); 
                XmlSerializer[] serializers = null; 
                Type type;
                object thisLock = new object(); 

                internal SerializerGenerationContext(Type type)
                {
                    this.type = type; 
                }
 
                // returns a stub to a serializer 
                internal SerializerStub AddSerializer(XmlMembersMapping mapping)
                { 
                    int handle = -1;
                    if (mapping != null)
                    {
                        handle = ((IList)Mappings).Add(mapping); 
                    }
 
                    return new SerializerStub(this, mapping, handle); 
                }
 
                internal XmlSerializer GetSerializer(int handle)
                {
                    if (handle < 0)
                    { 
                        return null;
                    } 
 
                    if (this.serializers == null)
                    { 
                        lock (this.thisLock)
                        {
                            if (this.serializers == null)
                            { 
                                this.serializers = GenerateSerializers();
                            } 
                        } 
                    }
                    return this.serializers[handle]; 
                }

                XmlSerializer[] GenerateSerializers()
                { 
                    //this.Mappings may have duplicate mappings (for e.g. samed message contract is used by more than one operation)
                    //XmlSerializer.FromMappings require unique mappings. The following code uniquifies, calls FromMappings and deuniquifies 
                    List uniqueMappings = new List(); 
                    int[] uniqueIndexes = new int[Mappings.Count];
                    for (int srcIndex = 0;srcIndex < Mappings.Count; srcIndex++) 
                    {
                        XmlMembersMapping mapping = Mappings[srcIndex];
                        int uniqueIndex = uniqueMappings.IndexOf(mapping);
                        if (uniqueIndex < 0) 
                        {
                            uniqueMappings.Add(mapping); 
                            uniqueIndex = uniqueMappings.Count - 1; 
                        }
                        uniqueIndexes[srcIndex] = uniqueIndex; 
                    }
                    XmlSerializer[] uniqueSerializers = CreateSerializersFromMappings(uniqueMappings.ToArray(), type);
                    if (uniqueMappings.Count == Mappings.Count)
                        return uniqueSerializers; 
                    XmlSerializer[] serializers = new XmlSerializer[Mappings.Count];
                    for (int i = 0; i < Mappings.Count; i++) 
                    { 
                        serializers[i] = uniqueSerializers[uniqueIndexes[i]];
                    } 
                    return serializers;
                }

                ///  
                /// Critical - XmlSerializer.FromMappings has a LinkDemand
                /// Safe - LinkDemand is spurious, not protecting anything in particular 
                ///  
                [SecurityCritical, SecurityTreatAsSafe]
                XmlSerializer[] CreateSerializersFromMappings(XmlMapping[] mappings, Type type) 
                {
                    return XmlSerializer.FromMappings(mappings, type);
                }
            } 

            internal struct SerializerStub 
            { 
                readonly SerializerGenerationContext context;
 
                internal readonly XmlMembersMapping Mapping;
                internal readonly int Handle;

                internal SerializerStub(SerializerGenerationContext context, XmlMembersMapping mapping, int handle) 
                {
                    this.context = context; 
                    this.Mapping = mapping; 
                    this.Handle = handle;
                } 

                internal XmlSerializer GetSerializer()
                {
                    return context.GetSerializer(Handle); 
                }
            } 
 
            internal class XmlSerializerFaultContractInfo
            { 
                FaultContractInfo faultContractInfo;
                SerializerStub serializerStub;
                XmlQualifiedName faultContractElementName;
                XmlSerializerObjectSerializer serializer; 

                internal XmlSerializerFaultContractInfo(FaultContractInfo faultContractInfo, SerializerStub serializerStub, 
                    XmlQualifiedName faultContractElementName) 
                {
                    if (faultContractInfo == null) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("faultContractInfo");
                    }
                    if (faultContractElementName == null) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("faultContractElementName"); 
                    } 
                    this.faultContractInfo = faultContractInfo;
                    this.serializerStub = serializerStub; 
                    this.faultContractElementName = faultContractElementName;
                }

                internal FaultContractInfo FaultContractInfo 
                {
                    get { return this.faultContractInfo; } 
                } 

                internal XmlQualifiedName FaultContractElementName 
                {
                    get { return this.faultContractElementName; }
                }
 
                internal XmlSerializerObjectSerializer Serializer
                { 
                    get 
                    {
                        if (this.serializer == null) 
                            this.serializer = new XmlSerializerObjectSerializer(faultContractInfo.Detail, this.faultContractElementName, this.serializerStub.GetSerializer());
                        return this.serializer;
                    }
                } 
            }
 
            internal class MessageInfo : XmlSerializerOperationFormatter.MessageInfo 
            {
                SerializerStub headers; 
                SerializerStub body;
                OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable;
                MessageHeaderDescription unknownHeaderDescription;
                MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts; 

                internal XmlMembersMapping BodyMapping 
                { 
                    get { return body.Mapping; }
                } 

                internal override XmlSerializer BodySerializer
                {
                    get { return body.GetSerializer(); } 
                }
 
                internal XmlMembersMapping HeadersMapping 
                {
                    get { return headers.Mapping; } 
                }

                internal override XmlSerializer HeaderSerializer
                { 
                    get { return headers.GetSerializer(); }
                } 
 
                internal override OperationFormatter.MessageHeaderDescriptionTable HeaderDescriptionTable
                { 
                    get { return this.headerDescriptionTable; }
                }

                internal override MessageHeaderDescription UnknownHeaderDescription 
                {
                    get { return this.unknownHeaderDescription; } 
                } 

                internal override MessagePartDescriptionCollection RpcEncodedTypedMessageBodyParts 
                {
                    get { return rpcEncodedTypedMessageBodyParts; }
                }
 
                internal void SetBody(SerializerStub body, MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts)
                { 
                    this.body = body; 
                    this.rpcEncodedTypedMessageBodyParts = rpcEncodedTypedMessageBodyParts;
                } 

                internal void SetHeaders(SerializerStub headers)
                {
                    this.headers = headers; 
                }
 
                internal void SetHeaderDescriptionTable(OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable) 
                {
                    this.headerDescriptionTable = headerDescriptionTable; 
                }

                internal void SetUnknownHeaderDescription(MessageHeaderDescription unknownHeaderDescription)
                { 
                    this.unknownHeaderDescription = unknownHeaderDescription;
                } 
 
            }
        } 
    }

    static class XmlSerializerHelper
    { 
        static internal XmlReflectionMember GetXmlReflectionMember(MessagePartDescription part, bool isRpc, bool isEncoded, bool isWrapped)
        { 
            string ns = isRpc ? null : part.Namespace; 
            ICustomAttributeProvider additionalAttributesProvider = null;
            if (isEncoded  || part.AdditionalAttributesProvider is MemberInfo) 
                additionalAttributesProvider = part.AdditionalAttributesProvider;
            XmlName memberName = string.IsNullOrEmpty(part.UniquePartName) ? null : new XmlName(part.UniquePartName, true /*isEncoded*/);
            XmlName elementName = part.XmlName;
            return GetXmlReflectionMember(memberName, elementName, ns, part.Type, additionalAttributesProvider, part.Multiple, isEncoded, isWrapped); 
        }
 
        static internal XmlReflectionMember GetXmlReflectionMember(XmlName memberName, XmlName elementName, string ns, Type type, ICustomAttributeProvider additionalAttributesProvider, bool isMultiple, bool isEncoded, bool isWrapped) 
        {
            if (isEncoded && isMultiple) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMultiplePartsNotAllowedInEncoded, elementName.DecodedName, ns)));

            XmlReflectionMember member = new XmlReflectionMember();
            member.MemberName = (memberName ?? elementName).DecodedName; 
            member.MemberType = type;
            if (member.MemberType.IsByRef) 
                member.MemberType = member.MemberType.GetElementType(); 
            if (isMultiple)
                member.MemberType = member.MemberType.MakeArrayType(); 
            if (additionalAttributesProvider != null)
            {
                if (isEncoded)
                    member.SoapAttributes = new SoapAttributes(additionalAttributesProvider); 
                else
                    member.XmlAttributes = new XmlAttributes(additionalAttributesProvider); 
            } 
            if (isEncoded)
            { 
                if (member.SoapAttributes == null)
                    member.SoapAttributes = new SoapAttributes();
                else
                { 
                    Type invalidAttributeType = null;
                    if (member.SoapAttributes.SoapAttribute != null) 
                        invalidAttributeType = typeof(SoapAttributeAttribute); 
                    else if (member.SoapAttributes.SoapIgnore)
                        invalidAttributeType = typeof(SoapIgnoreAttribute); 
                    else if (member.SoapAttributes.SoapType != null)
                        invalidAttributeType = typeof(SoapTypeAttribute);
                    if (invalidAttributeType != null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidSoapAttribute, invalidAttributeType, elementName.DecodedName))); 
                }
                if (member.SoapAttributes.SoapElement == null) 
                    member.SoapAttributes.SoapElement = new SoapElementAttribute(elementName.DecodedName); 

            } 
            else
            {
                if (member.XmlAttributes == null)
                    member.XmlAttributes = new XmlAttributes(); 
                else
                { 
                    Type invalidAttributeType = null; 
                    if (member.XmlAttributes.XmlAttribute != null)
                        invalidAttributeType = typeof(XmlAttributeAttribute); 
                    else if (member.XmlAttributes.XmlAnyAttribute != null && !isWrapped)
                        invalidAttributeType = typeof(XmlAnyAttributeAttribute);
                    else if (member.XmlAttributes.XmlChoiceIdentifier != null)
                        invalidAttributeType = typeof(XmlChoiceIdentifierAttribute); 
                    else if (member.XmlAttributes.XmlIgnore)
                        invalidAttributeType = typeof(XmlIgnoreAttribute); 
                    else if (member.XmlAttributes.Xmlns) 
                        invalidAttributeType = typeof(XmlNamespaceDeclarationsAttribute);
                    else if (member.XmlAttributes.XmlText != null) 
                        invalidAttributeType = typeof(XmlTextAttribute);
                    else if (member.XmlAttributes.XmlEnum != null)
                        invalidAttributeType = typeof(XmlEnumAttribute);
                    if (invalidAttributeType != null) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(isWrapped?SR.SFxInvalidXmlAttributeInWrapped:SR.SFxInvalidXmlAttributeInBare, invalidAttributeType, elementName.DecodedName)));
                    if (member.XmlAttributes.XmlArray != null && isMultiple) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxXmlArrayNotAllowedForMultiple, elementName.DecodedName, ns))); 

                } 


                bool isArray = member.MemberType.IsArray;
                if ((isArray && !isMultiple && member.MemberType != typeof(byte[])) || 
                   (!isArray && typeof(IEnumerable).IsAssignableFrom(member.MemberType) && member.MemberType != typeof(string) && !typeof(XmlNode).IsAssignableFrom(member.MemberType) && !typeof(IXmlSerializable).IsAssignableFrom(member.MemberType)))
                { 
                    if (member.XmlAttributes.XmlArray != null) 
                    {
                        if (member.XmlAttributes.XmlArray.Namespace == null) 
                            member.XmlAttributes.XmlArray.Namespace = ns;
                    }
                    else if (HasNoXmlParameterAttributes(member.XmlAttributes))
                    { 
                        member.XmlAttributes.XmlArray = new XmlArrayAttribute();
                        member.XmlAttributes.XmlArray.ElementName = elementName.DecodedName; 
                        member.XmlAttributes.XmlArray.Namespace = ns; 
                    }
                } 
                else
                {
                    if (member.XmlAttributes.XmlElements == null || member.XmlAttributes.XmlElements.Count == 0)
                    { 
                        if (HasNoXmlParameterAttributes(member.XmlAttributes))
                        { 
                            XmlElementAttribute elementAttribute = new XmlElementAttribute(); 
                            elementAttribute.ElementName = elementName.DecodedName;
                            elementAttribute.Namespace = ns; 
                            member.XmlAttributes.XmlElements.Add(elementAttribute);
                        }
                    }
                    else 
                    {
                        bool hasNullType = false; 
                        foreach (XmlElementAttribute elementAttribute in member.XmlAttributes.XmlElements) 
                        {
                            if (elementAttribute.Namespace == null) 
                                elementAttribute.Namespace = ns;
                            if (elementAttribute.Type == null)
                                hasNullType = true;
                        } 
                        if (!hasNullType && member.XmlAttributes.XmlChoiceIdentifier == null && member.XmlAttributes.XmlText == null)
                        { 
                            XmlElementAttribute elementAttribute = new XmlElementAttribute(); 
                            elementAttribute.ElementName = elementName.DecodedName;
                            elementAttribute.Namespace = ns; 
                            member.XmlAttributes.XmlElements.Add(elementAttribute);
                        }
                    }
                } 
            }
            return member; 
        } 

        static bool HasNoXmlParameterAttributes(XmlAttributes xmlAttributes) 
        {
            return xmlAttributes.XmlAnyAttribute == null &&
                (xmlAttributes.XmlAnyElements == null || xmlAttributes.XmlAnyElements.Count == 0) &&
                xmlAttributes.XmlArray == null && 
                xmlAttributes.XmlAttribute == null &&
                !xmlAttributes.XmlIgnore && 
                xmlAttributes.XmlText == null && 
                xmlAttributes.XmlChoiceIdentifier == null &&
                (xmlAttributes.XmlElements == null || xmlAttributes.XmlElements.Count == 0) && 
                !xmlAttributes.Xmlns;
        }
    }
} 

// 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