SoapProtocolImporter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Web / System / Web / Services / Description / SoapProtocolImporter.cs / 1305376 / SoapProtocolImporter.cs

                            //------------------------------------------------------------------------------ 
//  
//     Copyright (c) Microsoft Corporation. All Rights Reserved.
//     Information Contained Herein is Proprietary and Confidential.
//   
//-----------------------------------------------------------------------------
namespace System.Web.Services.Description { 
 
    using System.Web.Services;
    using System.Web.Services.Protocols; 
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.Serialization.Advanced;
    using System.Xml.Schema; 
    using System.Collections;
    using System; 
    using System.Data; 
    using System.Data.Design;
    using System.Reflection; 
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Web.Services.Configuration;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Security.Permissions; 
    using System.Globalization; 
    using System.Threading;
 
    internal class SoapParameters {
        XmlMemberMapping ret;
        ArrayList parameters = new ArrayList();
        ArrayList inParameters = new ArrayList(); 
        ArrayList outParameters = new ArrayList();
        int checkSpecifiedCount; 
        int inCheckSpecifiedCount; 
        int outCheckSpecifiedCount;
 
        internal SoapParameters(XmlMembersMapping request, XmlMembersMapping response, string[] parameterOrder, CodeIdentifiers identifiers) {
            ArrayList requestList = new ArrayList();
            ArrayList responseList = new ArrayList();
 
            AddMappings(requestList, request);
            if (response != null) AddMappings(responseList, response); 
 
            if (parameterOrder != null) {
                for (int i = 0; i < parameterOrder.Length; i++) { 
                    string elementName = parameterOrder[i];
                    XmlMemberMapping requestMapping = FindMapping(requestList, elementName);
                    SoapParameter parameter = new SoapParameter();
                    if (requestMapping != null) { 
                        if (RemoveByRefMapping(responseList, requestMapping))
                            parameter.codeFlags = CodeFlags.IsByRef; 
                        parameter.mapping = requestMapping; 
                        requestList.Remove(requestMapping);
                        AddParameter(parameter); 
                    }
                    else {
                        XmlMemberMapping responseMapping = FindMapping(responseList, elementName);
                        if (responseMapping != null) { 
                            parameter.codeFlags = CodeFlags.IsOut;
                            parameter.mapping = responseMapping; 
                            responseList.Remove(responseMapping); 
                            AddParameter(parameter);
                        } 
                    }
                }
            }
 
            foreach (XmlMemberMapping requestMapping in requestList) {
                SoapParameter parameter = new SoapParameter(); 
                if (RemoveByRefMapping(responseList, requestMapping)) 
                    parameter.codeFlags = CodeFlags.IsByRef;
                parameter.mapping = requestMapping; 
                AddParameter(parameter);
            }

            if (responseList.Count > 0) { 
                if (!((XmlMemberMapping) responseList[0]).CheckSpecified) {
                    ret = (XmlMemberMapping)responseList[0]; 
                    responseList.RemoveAt(0); 
                }
                foreach (XmlMemberMapping responseMapping in responseList) { 
                    SoapParameter parameter = new SoapParameter();
                    parameter.mapping = responseMapping;
                    parameter.codeFlags = CodeFlags.IsOut;
                    AddParameter(parameter); 
                }
            } 
 
            foreach (SoapParameter parameter in parameters) {
                parameter.name = identifiers.MakeUnique(CodeIdentifier.MakeValid(parameter.mapping.MemberName)); 
            }
        }

        void AddParameter(SoapParameter parameter) { 
            parameters.Add(parameter);
            if (parameter.mapping.CheckSpecified) { 
                checkSpecifiedCount++; 
            }
            if (parameter.IsByRef) { 
                inParameters.Add(parameter);
                outParameters.Add(parameter);
                if (parameter.mapping.CheckSpecified) {
                    inCheckSpecifiedCount++; 
                    outCheckSpecifiedCount++;
                } 
            } else if (parameter.IsOut) { 
                outParameters.Add(parameter);
                if (parameter.mapping.CheckSpecified) 
                    outCheckSpecifiedCount++;
            }
            else {
                inParameters.Add(parameter); 
                if (parameter.mapping.CheckSpecified)
                    inCheckSpecifiedCount++; 
            } 
        }
 
        static bool RemoveByRefMapping(ArrayList responseList, XmlMemberMapping requestMapping) {
            XmlMemberMapping responseMapping = FindMapping(responseList, requestMapping.ElementName);
            if (responseMapping == null) return false;
            if (requestMapping.TypeFullName != responseMapping.TypeFullName) return false; 
            if (requestMapping.Namespace != responseMapping.Namespace) return false;
            if (requestMapping.MemberName != responseMapping.MemberName) return false; 
            responseList.Remove(responseMapping); 
            return true;
        } 

        static void AddMappings(ArrayList mappingsList, XmlMembersMapping mappings) {
            for (int i = 0; i < mappings.Count; i++) {
                mappingsList.Add(mappings[i]); 
            }
        } 
 
        static XmlMemberMapping FindMapping(ArrayList mappingsList, string elementName) {
            foreach (XmlMemberMapping mapping in mappingsList) 
                if (mapping.ElementName == elementName)
                    return mapping;
            return null;
        } 

        internal XmlMemberMapping Return { 
            get { return ret; } 
        }
 
        internal IList Parameters {
            get { return parameters; }
        }
 
        internal IList InParameters {
            get { return inParameters; } 
        } 

        internal IList OutParameters { 
            get { return outParameters; }
        }

        internal int CheckSpecifiedCount { 
            get { return checkSpecifiedCount; }
        } 
 
        internal int InCheckSpecifiedCount {
            get { return inCheckSpecifiedCount; } 
        }

        internal int OutCheckSpecifiedCount {
            get { return outCheckSpecifiedCount; } 
        }
    } 
 
    internal class SoapParameter {
        internal CodeFlags codeFlags; 
        internal string name;
        internal XmlMemberMapping mapping;
        internal string specifiedName;
 
        internal bool IsOut {
            get { return (codeFlags & CodeFlags.IsOut) != 0; } 
        } 

        internal bool IsByRef { 
            get { return (codeFlags & CodeFlags.IsByRef) != 0; }
        }

        internal static string[] GetTypeFullNames(IList parameters, int specifiedCount, CodeDomProvider codeProvider) { 
            string[] typeFullNames = new string[parameters.Count + specifiedCount];
            GetTypeFullNames(parameters, typeFullNames, 0, specifiedCount, codeProvider); 
            return typeFullNames; 
        }
 
        internal static void GetTypeFullNames(IList parameters, string[] typeFullNames, int start, int specifiedCount, CodeDomProvider codeProvider) {
            int specified = 0;
            for (int i = 0; i < parameters.Count; i++) {
                typeFullNames[i + start + specified] = WebCodeGenerator.FullTypeName(((SoapParameter)parameters[i]).mapping, codeProvider); 
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
                    specified++; 
                    typeFullNames[i + start + specified] = typeof(bool).FullName; 
                }
            } 
        }

        internal static string[] GetNames(IList parameters, int specifiedCount) {
            string[] names = new string[parameters.Count + specifiedCount]; 
            GetNames(parameters, names, 0, specifiedCount);
            return names; 
        } 

        internal static void GetNames(IList parameters, string[] names, int start, int specifiedCount) { 
            int specified = 0;
            for (int i = 0; i < parameters.Count; i++) {
                names[i + start + specified] = ((SoapParameter)parameters[i]).name;
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) { 
                    specified++;
                    names[i + start + specified] = ((SoapParameter) parameters[i]).specifiedName; 
                } 
            }
        } 

        internal static CodeFlags[] GetCodeFlags(IList parameters, int specifiedCount) {
            CodeFlags[] codeFlags = new CodeFlags[parameters.Count + specifiedCount];
            GetCodeFlags(parameters, codeFlags, 0, specifiedCount); 
            return codeFlags;
        } 
 
        internal static void GetCodeFlags(IList parameters, CodeFlags[] codeFlags, int start, int specifiedCount) {
            int specified = 0; 
            for (int i = 0; i < parameters.Count; i++) {
                codeFlags[i + start + specified] = ((SoapParameter)parameters[i]).codeFlags;
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
                    specified++; 
                    codeFlags[i + start + specified] = ((SoapParameter) parameters[i]).codeFlags;
                } 
            } 
        }
    } 

    internal class GlobalSoapHeader {
        internal string fieldName;
        internal XmlTypeMapping mapping; 
        internal bool isEncoded;
    } 
 
    internal class LocalSoapHeader {
        internal SoapHeaderDirection direction; 
        internal string fieldName;
    }

    ///  
    /// 
    ///    [To be supplied.] 
    ///  
    [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
    [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")] 
    public class SoapProtocolImporter : ProtocolImporter {
        XmlSchemaImporter xmlImporter;
        XmlCodeExporter xmlExporter;
        SoapSchemaImporter soapImporter; 
        SoapCodeExporter soapExporter;
        ArrayList xmlMembers = new ArrayList(); 
        ArrayList soapMembers = new ArrayList(); 
        Hashtable headers = new Hashtable();
        Hashtable classHeaders = new Hashtable(); 
        ArrayList propertyNames = new ArrayList();
        ArrayList propertyValues = new ArrayList();
        SoapExtensionImporter[] extensions;
        SoapTransportImporter transport; 
        SoapBinding soapBinding;
        ArrayList codeClasses = new ArrayList(); 
        static TypedDataSetSchemaImporterExtension typedDataSetSchemaImporterExtension; 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        public override string ProtocolName { 
            get { return "Soap"; }
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        public SoapBinding SoapBinding {
            get { return soapBinding; } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        public SoapSchemaImporter SoapImporter {
            get { return soapImporter; }
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        public XmlSchemaImporter XmlImporter {
            get { return xmlImporter; }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        public XmlCodeExporter XmlExporter { 
            get { return xmlExporter; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public SoapCodeExporter SoapExporter {
            get { return soapExporter; } 
        }

        static TypedDataSetSchemaImporterExtension TypedDataSetSchemaImporterExtension {
            get { 
                if (typedDataSetSchemaImporterExtension == null) {
                    typedDataSetSchemaImporterExtension = new TypedDataSetSchemaImporterExtension(); 
                } 
                return typedDataSetSchemaImporterExtension;
            } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        protected override void BeginNamespace() { 
            try {
                MethodNames.Clear(); 
                ExtraCodeClasses.Clear();
                soapImporter = new SoapSchemaImporter(AbstractSchemas, ServiceImporter.CodeGenerationOptions, ImportContext);
                xmlImporter = new XmlSchemaImporter(ConcreteSchemas, ServiceImporter.CodeGenerationOptions, ServiceImporter.CodeGenerator, ImportContext);
                foreach (Type extensionType in ServiceImporter.Extensions) { 
                    xmlImporter.Extensions.Add(extensionType.FullName, extensionType);
                } 
                // use cached version of typed DataSetSchemaImporterExtension for /sharetypes feature 
                //
                xmlImporter.Extensions.Add(TypedDataSetSchemaImporterExtension); 
                xmlImporter.Extensions.Add(new DataSetSchemaImporterExtension());
                xmlExporter = new XmlCodeExporter(this.CodeNamespace, ServiceImporter.CodeCompileUnit, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
                soapExporter = new SoapCodeExporter(this.CodeNamespace, null, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
            } 
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
                    throw; 
                }
                throw new InvalidOperationException(Res.GetString(Res.InitFailed), e); 
            }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override void EndNamespace() {
            // need to preprocess all exported schemas to make sure that IXmlSerializable schemas are Merged and the resulting set is valid 
            ConcreteSchemas.Compile(null, false);

            foreach (GlobalSoapHeader soapHeader in headers.Values) {
                if (soapHeader.isEncoded) 
                    soapExporter.ExportTypeMapping(soapHeader.mapping);
                else 
                    xmlExporter.ExportTypeMapping(soapHeader.mapping); 
            }
 
            foreach (XmlMembersMapping member in xmlMembers)
                xmlExporter.ExportMembersMapping(member);

            foreach (XmlMembersMapping member in soapMembers) 
                soapExporter.ExportMembersMapping(member);
 
            // NOTE, [....], we are sharing the SoapInclude and XmlInclude attributes of the 
            // class among ALL classes generated, This is probably OK, since doing to per
            // class would probably result in the same set of includes if the user 
            // has object as a return value (meaning 'all' types are OK).
            foreach (CodeTypeDeclaration codeClass in codeClasses) {
                foreach (CodeAttributeDeclaration attribute in xmlExporter.IncludeMetadata) {
                    codeClass.CustomAttributes.Add(attribute); 
                }
                foreach (CodeAttributeDeclaration attribute in soapExporter.IncludeMetadata) { 
                    codeClass.CustomAttributes.Add(attribute); 
                }
            } 
            foreach(CodeTypeDeclaration declaration in ExtraCodeClasses) {
                this.CodeNamespace.Types.Add(declaration);
            }
            CodeGenerator.ValidateIdentifiers(CodeNamespace); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected override bool IsBindingSupported() {
            SoapBinding soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
            if (soapBinding == null || soapBinding.GetType() != typeof(SoapBinding)) return false; 

            if (GetTransport(soapBinding.Transport) == null) { 
                UnsupportedBindingWarning(Res.GetString(Res.ThereIsNoSoapTransportImporterThatUnderstands1, soapBinding.Transport)); 
                return false;
            } 

            return true;
        }
 
        internal SoapTransportImporter GetTransport(string transport) {
            foreach (Type type in WebServicesSection.Current.SoapTransportImporters) 
            { 
                SoapTransportImporter transportImporter = (SoapTransportImporter)Activator.CreateInstance(type);
                transportImporter.ImportContext = this; 
                if (transportImporter.IsSupportedTransport(transport)) return transportImporter;
            }
            return null;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override CodeTypeDeclaration BeginClass() {
            MethodNames.Clear();

            soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding)); 
            transport = GetTransport(soapBinding.Transport);
 
            Type[] requiredTypes = new Type[] { typeof(SoapDocumentMethodAttribute), typeof(XmlAttributeAttribute), typeof(WebService), typeof(Object), typeof(DebuggerStepThroughAttribute), typeof(DesignerCategoryAttribute) }; 
            WebCodeGenerator.AddImports(this.CodeNamespace, WebCodeGenerator.GetNamespacesForTypes(requiredTypes));
            CodeFlags flags = 0; 
            if (Style == ServiceDescriptionImportStyle.Server)
                flags = CodeFlags.IsAbstract;
            else if (Style == ServiceDescriptionImportStyle.ServerInterface)
                flags = CodeFlags.IsInterface; 
            CodeTypeDeclaration codeClass = WebCodeGenerator.CreateClass(this.ClassName, null,
                new string[0], null, CodeFlags.IsPublic | flags, 
                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)); 

            codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 
            if (Style == ServiceDescriptionImportStyle.Client) {
                codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DebuggerStepThroughAttribute).FullName));
                codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DesignerCategoryAttribute).FullName, new CodeAttributeArgument[] {new CodeAttributeArgument(new CodePrimitiveExpression("code"))}));
            } 
            else if (Style == ServiceDescriptionImportStyle.Server) {
                CodeAttributeDeclaration webService = new CodeAttributeDeclaration(typeof(WebServiceAttribute).FullName); 
                string targetNs = Service != null ? Service.ServiceDescription.TargetNamespace : Binding.ServiceDescription.TargetNamespace; 
                webService.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(targetNs)));
                codeClass.CustomAttributes.Add(webService); 
            }

            CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(typeof(WebServiceBindingAttribute).FullName);
            attribute.Arguments.Add(new CodeAttributeArgument("Name", new CodePrimitiveExpression(XmlConvert.DecodeName(Binding.Name)))); 
            attribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(Binding.ServiceDescription.TargetNamespace)));
 
            codeClass.CustomAttributes.Add(attribute); 

            codeClasses.Add(codeClass); 
            classHeaders.Clear();
            return codeClass;
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        protected override void EndClass() { 
            if (transport != null)
                transport.ImportClass();
            soapBinding = null;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override bool IsOperationFlowSupported(OperationFlow flow) {
            return flow == OperationFlow.OneWay || flow == OperationFlow.RequestResponse;
        }
 
        void BeginMetadata() {
            propertyNames.Clear(); 
            propertyValues.Clear(); 
        }
 
        bool MetadataPropertiesAdded {
            get { return propertyNames.Count > 0; }
        }
 
        void AddMetadataProperty(string name, object value) {
            AddMetadataProperty(name, new CodePrimitiveExpression(value)); 
        } 

        void AddMetadataProperty(string name, CodeExpression expr) { 
            propertyNames.Add(name);
            propertyValues.Add(expr);
        }
 
        void EndMetadata(CodeAttributeDeclarationCollection metadata, Type attributeType, string parameter) {
            CodeExpression[] parameters; 
            if (parameter == null) { 
                parameters = new CodeExpression[0];
            } 
            else {
                parameters = new CodeExpression[1] { new CodePrimitiveExpression(parameter) };
            }
            WebCodeGenerator.AddCustomAttribute(metadata, attributeType, parameters, 
                                  (string[])propertyNames.ToArray(typeof(string)),
                                  (CodeExpression[])propertyValues.ToArray(typeof(CodeExpression))); 
        } 

        void GenerateExtensionMetadata(CodeAttributeDeclarationCollection metadata) { 
            if (extensions == null) {
                TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionImporterTypes;
                extensions = new SoapExtensionImporter[extensionTypes.Count];
                for (int i = 0; i < extensions.Length; i++) { 
                    SoapExtensionImporter extension = (SoapExtensionImporter)Activator.CreateInstance(extensionTypes[i].Type);
                    extension.ImportContext = this; 
                    extensions[i] = extension; 
                }
            } 
            foreach (SoapExtensionImporter extension in extensions) {
                extension.ImportMethod(metadata);
            }
        } 

        void PrepareHeaders(MessageBinding messageBinding) { 
            // By default, map all headers to properties on the generated class 
            // ExtensionImporters can modify this behavior by clearing the flag
            SoapHeaderBinding[] headers = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding)); 
            foreach (SoapHeaderBinding header in headers) {
                header.MapToProperty = true;
            }
        } 

        void GenerateHeaders(CodeAttributeDeclarationCollection metadata, SoapBindingUse use, bool rpc, MessageBinding requestMessage, MessageBinding responseMessage) { 
            Hashtable localHeaders = new Hashtable(); 

            for (int i = 0; i < 2; ++ i) { 
                MessageBinding messageBinding;
                SoapHeaderDirection direction;
                if (i == 0) {
                    messageBinding = requestMessage; 
                    direction = SoapHeaderDirection.In;
                } 
                else if (responseMessage != null) { 
                    messageBinding = responseMessage;
                    direction = SoapHeaderDirection.Out; 
                }
                else
                    continue;
 
                SoapHeaderBinding[] headerBindings = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
                foreach (SoapHeaderBinding header in headerBindings) { 
                    // Skip headers which should not be mapped to properties (extension importers can control this) 
                    if (!header.MapToProperty) continue;
 
                    if (use != header.Use) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionHeaderAndBodyUseMismatch));
                    if (use == SoapBindingUse.Encoded && !IsSoapEncodingPresent(header.Encoding) )
                        throw new InvalidOperationException(Res.GetString(Res.WebUnknownEncodingStyle, header.Encoding));
 
                    Message message = ServiceDescriptions.GetMessage(header.Message);
                    if (message == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessage2, header.Message.Name, header.Message.Namespace)); 
 
                    MessagePart part = message.FindPartByName(header.Part);
                    if (part == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessagePartForMessageFromNamespace3, part.Name, header.Message.Name, header.Message.Namespace)); 

                    XmlTypeMapping mapping;
                    string key;
                    if (use == SoapBindingUse.Encoded) { 
                        if (part.Type.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartTypeRequired, part.Name, header.Message.Name, header.Message.Namespace));
                        if (!part.Element.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartElementWarning, part.Name, header.Message.Name, header.Message.Namespace)); 
                        mapping = soapImporter.ImportDerivedTypeMapping(part.Type, typeof(SoapHeader), true); 
                        key = "type=" + part.Type.ToString();
                    } 
                    else {
                        if (part.Element.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartElementRequired, part.Name, header.Message.Name, header.Message.Namespace));
                        if (!part.Type.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartTypeWarning, part.Name, header.Message.Name, header.Message.Namespace));
                        mapping = xmlImporter.ImportDerivedTypeMapping(part.Element, typeof(SoapHeader), true); 
                        key = "element=" + part.Element.ToString();
                    } 
                    LocalSoapHeader localHeader = (LocalSoapHeader)localHeaders[key]; 
                    if (localHeader == null) {
                        GlobalSoapHeader globalHeader = (GlobalSoapHeader)classHeaders[key]; 
                        if (globalHeader == null) {
                            globalHeader = new GlobalSoapHeader();
                            globalHeader.isEncoded = use == SoapBindingUse.Encoded;
                            string fieldName = CodeIdentifier.MakeValid(mapping.ElementName); 
                            if (fieldName == mapping.TypeName) fieldName += "Value";
                            fieldName = MethodNames.AddUnique(fieldName, mapping); 
                            globalHeader.fieldName = fieldName; 
                            WebCodeGenerator.AddMember(CodeTypeDeclaration, mapping.TypeFullName, globalHeader.fieldName, null, null, CodeFlags.IsPublic, ServiceImporter.CodeGenerationOptions);
                            globalHeader.mapping = mapping; 
                            classHeaders.Add(key, globalHeader);
                            if (headers[key] == null)
                                headers.Add(key, globalHeader);
                        } 

                        localHeader = new  LocalSoapHeader(); 
                        localHeader.fieldName = globalHeader.fieldName; 
                        localHeader.direction = direction;
                        localHeaders.Add(key, localHeader); 
                    }
                    else {
                        if (localHeader.direction != direction)
                            localHeader.direction = SoapHeaderDirection.InOut; 
                    }
                } 
            } 

            foreach (LocalSoapHeader soapHeader in localHeaders.Values) { 
                BeginMetadata();
                if (soapHeader.direction == SoapHeaderDirection.Out) {
                    AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.Out.ToString()));
                } 
                else if (soapHeader.direction == SoapHeaderDirection.InOut) {
                    AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.InOut.ToString())); 
                } 

                EndMetadata(metadata, typeof(SoapHeaderAttribute), soapHeader.fieldName); 
            }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override CodeMemberMethod GenerateMethod() {
            Message requestMessage; 
            Message responseMessage;
            string[] parameterOrder;
            SoapBodyBinding soapRequestBinding;
            SoapBodyBinding soapResponseBinding; 
            MessageBinding requestBinding;
            MessageBinding responseBinding; 
 
            SoapOperationBinding soapOperationBinding = (SoapOperationBinding)this.OperationBinding.Extensions.Find(typeof(SoapOperationBinding));
            if (soapOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingSoapOperationBinding0)); 

            SoapBindingStyle soapBindingStyle = soapOperationBinding.Style;
            if (soapBindingStyle == SoapBindingStyle.Default)
                soapBindingStyle = SoapBinding.Style; 
            if (soapBindingStyle == SoapBindingStyle.Default)
                soapBindingStyle = SoapBindingStyle.Document; 
 
            parameterOrder = this.Operation.ParameterOrder;
 
            requestMessage = this.InputMessage;
            requestBinding = this.OperationBinding.Input;
            soapRequestBinding = (SoapBodyBinding)this.OperationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
            if (soapRequestBinding == null) { 
                UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyInputBinding0));
                return null; 
            } 

            if (this.Operation.Messages.Output != null) { 
                responseMessage = this.OutputMessage;
                responseBinding = this.OperationBinding.Output;
                soapResponseBinding = (SoapBodyBinding)this.OperationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
                if (soapResponseBinding == null) { 
                    UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyOutputBinding0));
                    return null; 
                } 
            }
            else { 
                responseMessage = null;
                responseBinding = null;
                soapResponseBinding = null;
            } 

            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection(); 
 
            PrepareHeaders(requestBinding);
            if (responseBinding != null) PrepareHeaders(responseBinding); 

            string requestMessageName;
            string responseMessageName = null;
 
            requestMessageName = !String.IsNullOrEmpty(requestBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? requestBinding.Name : this.Operation.Name; // per WSDL 1.1 sec 3.5
            requestMessageName = XmlConvert.DecodeName(requestMessageName); 
 
            if (responseBinding != null) {
                responseMessageName = !String.IsNullOrEmpty(responseBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? responseBinding.Name : this.Operation.Name + "Response"; // per WSDL 1.1 sec 3.5 
                responseMessageName = XmlConvert.DecodeName(responseMessageName);
            }

            GenerateExtensionMetadata(metadata); 
            GenerateHeaders(metadata, soapRequestBinding.Use, soapBindingStyle == SoapBindingStyle.Rpc, requestBinding, responseBinding);
 
            MessagePart[] requestParts = GetMessageParts(requestMessage, soapRequestBinding); 
            bool hasWrapper;
            if (!CheckMessageStyles(MethodName, requestParts, soapRequestBinding, soapBindingStyle, out hasWrapper)) 
                return null;

            MessagePart[] responseParts = null;
            if (responseMessage != null) { 
                responseParts = GetMessageParts(responseMessage, soapResponseBinding);
                bool responseHasWrapper; 
                if (!CheckMessageStyles(MethodName, responseParts, soapResponseBinding, soapBindingStyle, out responseHasWrapper)) 
                    return null;
 
                // since we're using a potentially inaccurate heuristic to determine whether there's a wrapper,
                // if we disagree about the request and response we should assume there isn't a wrapper.
                if (hasWrapper != responseHasWrapper)
                    hasWrapper = false; 
            }
 
            bool wrapperNamesMatter = (soapBindingStyle != SoapBindingStyle.Rpc && hasWrapper) || (soapRequestBinding.Use == SoapBindingUse.Literal && soapBindingStyle == SoapBindingStyle.Rpc); 

            XmlMembersMapping request = ImportMessage(requestMessageName, requestParts, soapRequestBinding, soapBindingStyle, hasWrapper); 
            if (request == null) return null;

            XmlMembersMapping response = null;
 
            if (responseMessage != null) {
                response = ImportMessage(responseMessageName, responseParts, soapResponseBinding, soapBindingStyle, hasWrapper); 
                if (response == null) return null; 
            }
 
            string methodName = CodeIdentifier.MakeValid(XmlConvert.DecodeName(this.Operation.Name));
            if (ClassName == methodName) {
                methodName = "Call" + methodName;
            } 
            string uniqueMethodName = MethodNames.AddUnique(CodeIdentifier.MakeValid(XmlConvert.DecodeName(methodName)), this.Operation);
            bool differentNames = methodName != uniqueMethodName; 
 
            CodeIdentifiers localIdentifiers = new CodeIdentifiers(false);
            localIdentifiers.AddReserved(uniqueMethodName); 

            SoapParameters parameters = new SoapParameters(request, response, parameterOrder, MethodNames);

            foreach (SoapParameter param in parameters.Parameters) { 
                if ((param.IsOut || param.IsByRef) && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReferenceParameters)) {
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReferenceParameters, ServiceImporter.CodeGenerator.GetType().Name)); 
                    return null; 
                }
                param.name = localIdentifiers.AddUnique(param.name, null); 
                if (param.mapping.CheckSpecified)
                    param.specifiedName = localIdentifiers.AddUnique(param.name + "Specified", null);
            }
 
            if (!(Style == ServiceDescriptionImportStyle.Client) || differentNames) {
                BeginMetadata(); 
                if (differentNames) AddMetadataProperty("MessageName", uniqueMethodName); 
                EndMetadata(metadata, typeof(WebMethodAttribute), null);
            } 

            BeginMetadata();
            if (wrapperNamesMatter && request.ElementName.Length > 0 && request.ElementName != uniqueMethodName)
                AddMetadataProperty("RequestElementName", request.ElementName); 
            if (request.Namespace != null)
                AddMetadataProperty("RequestNamespace", request.Namespace); 
            if (response == null) { 
                AddMetadataProperty("OneWay", true);
            } 
            else {
                if (wrapperNamesMatter && response.ElementName.Length > 0 && response.ElementName != (uniqueMethodName + "Response"))
                    AddMetadataProperty("ResponseElementName", response.ElementName);
                if (response.Namespace != null) 
                    AddMetadataProperty("ResponseNamespace", response.Namespace);
            } 
 
            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                if (soapRequestBinding.Use != SoapBindingUse.Encoded) { 
                    AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
                }
                EndMetadata(metadata, typeof(SoapRpcMethodAttribute), soapOperationBinding.SoapAction);
            } 
            else {
                AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G"))); 
                AddMetadataProperty("ParameterStyle", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapParameterStyle).FullName), Enum.Format(typeof(SoapParameterStyle), hasWrapper ? SoapParameterStyle.Wrapped : SoapParameterStyle.Bare, "G"))); 
                EndMetadata(metadata, typeof(SoapDocumentMethodAttribute), soapOperationBinding.SoapAction);
            } 
            IsEncodedBinding = IsEncodedBinding || (soapRequestBinding.Use == SoapBindingUse.Encoded);

            CodeAttributeDeclarationCollection[] paramsMetadata = new CodeAttributeDeclarationCollection[parameters.Parameters.Count + parameters.CheckSpecifiedCount];
            int j = 0; 
            CodeAttributeDeclaration ignoreAttribute = new CodeAttributeDeclaration(typeof(XmlIgnoreAttribute).FullName);
            foreach (SoapParameter parameter in parameters.Parameters) { 
                paramsMetadata[j] = new CodeAttributeDeclarationCollection(); 
                if (soapRequestBinding.Use == SoapBindingUse.Encoded)
                    soapExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, parameter.name != parameter.mapping.MemberName); 
                else {
                    string ns = soapBindingStyle == SoapBindingStyle.Rpc ? parameter.mapping.Namespace : parameter.IsOut ? response.Namespace : request.Namespace;
                    bool forceUseMemberName = parameter.name != parameter.mapping.MemberName;
                    xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping,  ns, forceUseMemberName); 
                    if (parameter.mapping.CheckSpecified) {
                        j++; 
                        paramsMetadata[j] = new CodeAttributeDeclarationCollection(); 
                        xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, parameter.specifiedName != parameter.mapping.MemberName + "Specified");
                        paramsMetadata[j].Add(ignoreAttribute); 
                    }
                }
                if (paramsMetadata[j].Count > 0  && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ParameterAttributes)) {
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportParameterAttributes, ServiceImporter.CodeGenerator.GetType().Name)); 
                    return null;
                } 
                j++; 
            }
 
            CodeFlags[] parameterFlags = SoapParameter.GetCodeFlags(parameters.Parameters, parameters.CheckSpecifiedCount);
            string[] parameterTypes = SoapParameter.GetTypeFullNames(parameters.Parameters, parameters.CheckSpecifiedCount, ServiceImporter.CodeGenerator);
            string returnType = parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
 
            CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, methodName,
                                        parameterFlags, 
                                        parameterTypes, 
                                        SoapParameter.GetNames(parameters.Parameters, parameters.CheckSpecifiedCount),
                                        paramsMetadata, 
                                        returnType,
                                        metadata,
                                        CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract));
 
            mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
 
            if (parameters.Return != null) { 
                if (soapRequestBinding.Use == SoapBindingUse.Encoded)
                    soapExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, parameters.Return.ElementName != uniqueMethodName + "Result"); 
                else
                    xmlExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, response.Namespace, parameters.Return.ElementName != uniqueMethodName + "Result");

                if (mainCodeMethod.ReturnTypeCustomAttributes.Count != 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReturnTypeAttributes)) { 
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReturnTypeAttributes, ServiceImporter.CodeGenerator.GetType().Name));
                    return null; 
                } 
            }
 
            string resultsName = localIdentifiers.MakeUnique("results");

            if (Style == ServiceDescriptionImportStyle.Client) {
                bool oldAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateOldAsync) != 0; 
                bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) && 
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates); 
                CodeExpression[] invokeParams = new CodeExpression[2];
                CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount); 
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams);
                WriteReturnMappings(mainCodeMethod, invoke, parameters, resultsName);

                if (oldAsync) { 
                    int inCount = parameters.InParameters.Count + parameters.InCheckSpecifiedCount;
 
                    string[] asyncParameterTypes = new string[inCount + 2]; 
                    SoapParameter.GetTypeFullNames(parameters.InParameters, asyncParameterTypes, 0, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                    asyncParameterTypes[inCount] = typeof(AsyncCallback).FullName; 
                    asyncParameterTypes[inCount + 1] = typeof(object).FullName;

                    string[] asyncParameterNames = new string[inCount + 2];
                    SoapParameter.GetNames(parameters.InParameters, asyncParameterNames, 0, parameters.InCheckSpecifiedCount); 
                    asyncParameterNames[inCount] = "callback";
                    asyncParameterNames[inCount + 1] = "asyncState"; 
 
                    CodeFlags[] asyncParameterFlags = new CodeFlags[inCount + 2];
 
                    CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + uniqueMethodName,
                        asyncParameterFlags,
                        asyncParameterTypes,
                        asyncParameterNames, 
                        typeof(IAsyncResult).FullName,
                        null, 
                        CodeFlags.IsPublic); 

                    beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    invokeParams = new CodeExpression[4];
                    CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
                    invokeParams[2] = new CodeArgumentReferenceExpression("callback"); 
                    invokeParams[3] = new CodeArgumentReferenceExpression("asyncState");
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams); 
                    beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
 
                    int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
                    string[] asyncReturnTypes = new string[outCount + 1];
                    SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                    asyncReturnTypes[0] = typeof(IAsyncResult).FullName; 

                    string[] asyncReturnNames = new string[outCount + 1]; 
                    SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount); 
                    asyncReturnNames[0] = "asyncResult";
 
                    CodeFlags[] asyncReturnFlags = new CodeFlags[outCount + 1];
                    for (int i = 0; i < outCount; i++)
                        asyncReturnFlags[i + 1] = CodeFlags.IsOut;
 
                    CodeMemberMethod codeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + uniqueMethodName,
                        asyncReturnFlags, 
                        asyncReturnTypes, 
                        asyncReturnNames,
                        parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), 
                        null,
                        CodeFlags.IsPublic);

                    codeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    CodeExpression invokeParam = new CodeArgumentReferenceExpression("asyncResult"); 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { invokeParam }); 

                    WriteReturnMappings(codeMethod, invoke, parameters, resultsName); 
                }

                // new RAD Async pattern
                if (newAsync) { 
                    string methodKey = MethodSignature(uniqueMethodName, returnType, parameterFlags, parameterTypes);
                    DelegateInfo delegateInfo = (DelegateInfo)ExportContext[methodKey]; 
                    if (delegateInfo == null) { 
                        string handlerType = ClassNames.AddUnique(uniqueMethodName + "CompletedEventHandler", uniqueMethodName);
                        string handlerArgs = ClassNames.AddUnique(uniqueMethodName + "CompletedEventArgs", uniqueMethodName); 
                        delegateInfo = new DelegateInfo(handlerType, handlerArgs);
                    }
                    string handlerName = MethodNames.AddUnique(uniqueMethodName + "Completed", uniqueMethodName);
                    string asyncName = MethodNames.AddUnique(uniqueMethodName + "Async", uniqueMethodName); 
                    string callbackMember = MethodNames.AddUnique(uniqueMethodName + "OperationCompleted", uniqueMethodName);
                    string callbackName = MethodNames.AddUnique("On" + uniqueMethodName + "OperationCompleted", uniqueMethodName); 
 
                    // public event xxxCompletedEventHandler xxxCompleted;
                    WebCodeGenerator.AddEvent(this.CodeTypeDeclaration.Members, delegateInfo.handlerType, handlerName); 

                    // private SendOrPostCallback xxxOperationCompleted;
                    WebCodeGenerator.AddCallbackDeclaration(this.CodeTypeDeclaration.Members, callbackMember);
 
                    // create the pair of xxxAsync methods
                    string[] inParamNames = SoapParameter.GetNames(parameters.InParameters, parameters.InCheckSpecifiedCount); 
                    string userState = UniqueName("userState", inParamNames); 
                    CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName,
                        SoapParameter.GetTypeFullNames(parameters.InParameters, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator), inParamNames, callbackMember, callbackName, userState); 

                    // Generate InvokeAsync call
                    invokeParams = new CodeExpression[4];
                    CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount); 
                    invokeParams[2] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember);
                    invokeParams[3] = new CodeArgumentReferenceExpression(userState); 
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams);
                    asyncCodeMethod.Statements.Add(invoke); 

                    //  private void On_xxx_OperationCompleted(object arg) {..}
                    bool methodHasOutParameters = parameters.Return != null || parameters.OutParameters.Count > 0;
                    WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasOutParameters); 

                    if (ExportContext[methodKey] == null) { 
                        // public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args); 
                        WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasOutParameters ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName);
 
                        // Create strongly-typed Args class
                        if (methodHasOutParameters) {
                            int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
                            string[] asyncReturnTypes = new string[outCount + 1]; 
                            SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                            asyncReturnTypes[0] = parameters.Return == null ? null : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator); 
 
                            string[] asyncReturnNames = new string[outCount + 1];
                            SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount); 
                            asyncReturnNames[0] = parameters.Return == null ? null : "Result";
                            ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, asyncReturnTypes, asyncReturnNames, ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
                        }
                        ExportContext[methodKey] = delegateInfo; 
                    }
                } 
            } 
            return mainCodeMethod;
        } 

        void WriteReturnMappings(CodeMemberMethod codeMethod, CodeExpression invoke, SoapParameters parameters, string resultsName) {
            if (parameters.Return == null && parameters.OutParameters.Count == 0) {
                codeMethod.Statements.Add(new CodeExpressionStatement(invoke)); 
            }
            else { 
                codeMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), resultsName, invoke)); 

                int count = parameters.Return == null ? 0 : 1; 
                for (int i = 0; i < parameters.OutParameters.Count; i++) {
                    SoapParameter parameter = (SoapParameter)parameters.OutParameters[i];
                    CodeExpression target = new CodeArgumentReferenceExpression(parameter.name);
                    CodeExpression value = new CodeArrayIndexerExpression(); 
                    ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                    ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++)); 
                    value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameter.mapping, ServiceImporter.CodeGenerator), value); 
                    codeMethod.Statements.Add(new CodeAssignStatement(target, value));
                    if (parameter.mapping.CheckSpecified) { 
                        target = new CodeArgumentReferenceExpression(parameter.name + "Specified");
                        value = new CodeArrayIndexerExpression();
                        ((CodeArrayIndexerExpression) value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                        ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++)); 
                        value = new CodeCastExpression(typeof(bool).FullName, value);
                        codeMethod.Statements.Add(new CodeAssignStatement(target, value)); 
                    } 
                }
 
                if (parameters.Return != null) {
                    CodeExpression value = new CodeArrayIndexerExpression();
                    ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                    ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(0)); 
                    value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), value);
                    codeMethod.Statements.Add(new CodeMethodReturnStatement(value)); 
                } 
            }
        } 

        void CreateInvokeParams(CodeExpression[] invokeParams, string methodName, IList parameters, int checkSpecifiedCount) {
            invokeParams[0] = new CodePrimitiveExpression(methodName);
 
            CodeExpression[] values = new CodeExpression[parameters.Count + checkSpecifiedCount];
            int value = 0; 
            for (int i = 0; i < parameters.Count; i++) { 
                SoapParameter parameter = (SoapParameter)parameters[i];
                values[value++] = new CodeArgumentReferenceExpression(parameter.name); 
                if (parameter.mapping.CheckSpecified)
                    values[value++] = new CodeArgumentReferenceExpression(parameter.specifiedName);
            }
            invokeParams[1] = new CodeArrayCreateExpression(typeof(object).FullName, values); 
        }
 
        // returns false if we didn't like the message -- otherwise caller is safe to use body binding and binding style 
        bool CheckMessageStyles(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, out bool hasWrapper) {
            hasWrapper = false; 
            if (soapBodyBinding.Use == SoapBindingUse.Default) {
                soapBodyBinding.Use = SoapBindingUse.Literal;
            }
            if (soapBodyBinding.Use == SoapBindingUse.Literal) { 
                if (soapBindingStyle == SoapBindingStyle.Rpc) {
                    foreach (MessagePart part in parts) { 
                        if (!part.Element.IsEmpty) { 
                            UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInRpcUseLiteralMessageMustSpecify0));
                            return false; 
                        }
                    }
                    return true;
                } 
                if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
                    // special top-level any case 
                    if (!parts[0].Element.IsEmpty) { 
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
                        return false; 
                    }
                    XmlMembersMapping membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
                    if (membersMapping == null) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIsAny, parts[0].Type.Name, parts[0].Type.Namespace)); 
                        return false;
                    } 
                    return true; 
                }
                else { 
                    foreach (MessagePart part in parts) {
                        if (!part.Type.IsEmpty) {
                            UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
                            return false; 
                        }
                        if (part.Element.IsEmpty) { 
                            UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAUseLiteralMessageMustSpecify0)); 
                            return false;
                        } 
                    }
                }
            }
            else if (soapBodyBinding.Use == SoapBindingUse.Encoded) { 
                if (!IsSoapEncodingPresent(soapBodyBinding.Encoding)) {
                    UnsupportedOperationBindingWarning(Res.GetString(Res.TheEncodingIsNotSupported1, soapBodyBinding.Encoding)); 
                    return false; 
                }
                foreach (MessagePart part in parts) { 
                    if (!part.Element.IsEmpty) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingAnElementForUseEncodedMessageParts0));
                        return false;
                    } 
                    if (part.Type.IsEmpty) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAnUseEncodedMessageMustSpecify0)); 
                        return false; 
                    }
                } 
            }

            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                return true; 
            }
            else if (soapBindingStyle == SoapBindingStyle.Document) { 
                // NOTE, [....].  WSDL doesn't really let us figure out whether a document is 
                // in fact a struct containing parameters, so we apply a little heuristic here
                // in order to produce the appropriate programming model. 
                hasWrapper = (parts.Length == 1 && string.Compare(parts[0].Name, "parameters", StringComparison.Ordinal) == 0);
                return true;
            }
            return false; 
        }
 
        ///  
        ///
        protected virtual bool IsSoapEncodingPresent(string uriList) { 
            int iStart = 0;
            do {
                iStart = uriList.IndexOf(Soap.Encoding, iStart, StringComparison.Ordinal);
                if (iStart < 0) 
                    return false;
                int iEnd = iStart + Soap.Encoding.Length; 
                if (iStart == 0 || uriList[iStart-1] == ' ') 
                    if (iEnd == uriList.Length || uriList[iEnd] == ' ')
                        return true; 
                iStart = iEnd;
            } while (iStart < uriList.Length);
            return false;
        } 

        MessagePart[] GetMessageParts(Message message, SoapBodyBinding soapBodyBinding) { 
            MessagePart[] parts; 
            if (soapBodyBinding.Parts == null) {
                parts = new MessagePart[message.Parts.Count]; 
                message.Parts.CopyTo(parts, 0);
            }
            else {
                parts = message.FindPartsByName(soapBodyBinding.Parts); 
            }
            return parts; 
        } 

        XmlMembersMapping ImportMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) { 
            if (soapBodyBinding.Use == SoapBindingUse.Encoded)
                return ImportEncodedMessage(messageName, parts, soapBodyBinding, wrapped);
            else
                return ImportLiteralMessage(messageName, parts, soapBodyBinding, soapBindingStyle, wrapped); 
        }
 
        XmlMembersMapping ImportEncodedMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, bool wrapped) { 
            XmlMembersMapping membersMapping;
            if (wrapped) { 
                SoapSchemaMember schemaMember = new SoapSchemaMember();
                schemaMember.MemberName = parts[0].Name;
                schemaMember.MemberType = parts[0].Type;
                membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMember); 
            }
            else { 
                SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length]; 
                for (int i = 0; i < schemaMembers.Length; i++) {
                    MessagePart part = parts[i]; 
                    SoapSchemaMember schemaMember = new SoapSchemaMember();
                    schemaMember.MemberName = part.Name;
                    schemaMember.MemberType = part.Type;
                    schemaMembers[i] = schemaMember; 
                }
                membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers); 
            } 
            soapMembers.Add(membersMapping);
            return membersMapping; 
        }

        XmlMembersMapping ImportLiteralMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
            XmlMembersMapping membersMapping; 
            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length]; 
                for (int i = 0; i < schemaMembers.Length; i++) { 
                    MessagePart part = parts[i];
                    SoapSchemaMember schemaMember = new SoapSchemaMember(); 
                    schemaMember.MemberName = part.Name;
                    schemaMember.MemberType = part.Type;
                    schemaMembers[i] = schemaMember;
                } 
                membersMapping = xmlImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
            } 
            else if (wrapped) { 
                membersMapping = xmlImporter.ImportMembersMapping(parts[0].Element);
            } 
            else {
                if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
                    // special case for  at root
                    // we know this will work because we tried it earlier in CheckMessageStyles. 
                    membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
                    xmlMembers.Add(membersMapping); 
                    return membersMapping; 
                }
                XmlQualifiedName[] names = new XmlQualifiedName[parts.Length]; 
                for (int i = 0; i < parts.Length; i++)
                    names[i] = parts[i].Element;
                membersMapping = xmlImporter.ImportMembersMapping(names);
            } 
            xmlMembers.Add(membersMapping);
            return membersMapping; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  
//     Copyright (c) Microsoft Corporation. All Rights Reserved.
//     Information Contained Herein is Proprietary and Confidential.
//   
//-----------------------------------------------------------------------------
namespace System.Web.Services.Description { 
 
    using System.Web.Services;
    using System.Web.Services.Protocols; 
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.Serialization.Advanced;
    using System.Xml.Schema; 
    using System.Collections;
    using System; 
    using System.Data; 
    using System.Data.Design;
    using System.Reflection; 
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Web.Services.Configuration;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Security.Permissions; 
    using System.Globalization; 
    using System.Threading;
 
    internal class SoapParameters {
        XmlMemberMapping ret;
        ArrayList parameters = new ArrayList();
        ArrayList inParameters = new ArrayList(); 
        ArrayList outParameters = new ArrayList();
        int checkSpecifiedCount; 
        int inCheckSpecifiedCount; 
        int outCheckSpecifiedCount;
 
        internal SoapParameters(XmlMembersMapping request, XmlMembersMapping response, string[] parameterOrder, CodeIdentifiers identifiers) {
            ArrayList requestList = new ArrayList();
            ArrayList responseList = new ArrayList();
 
            AddMappings(requestList, request);
            if (response != null) AddMappings(responseList, response); 
 
            if (parameterOrder != null) {
                for (int i = 0; i < parameterOrder.Length; i++) { 
                    string elementName = parameterOrder[i];
                    XmlMemberMapping requestMapping = FindMapping(requestList, elementName);
                    SoapParameter parameter = new SoapParameter();
                    if (requestMapping != null) { 
                        if (RemoveByRefMapping(responseList, requestMapping))
                            parameter.codeFlags = CodeFlags.IsByRef; 
                        parameter.mapping = requestMapping; 
                        requestList.Remove(requestMapping);
                        AddParameter(parameter); 
                    }
                    else {
                        XmlMemberMapping responseMapping = FindMapping(responseList, elementName);
                        if (responseMapping != null) { 
                            parameter.codeFlags = CodeFlags.IsOut;
                            parameter.mapping = responseMapping; 
                            responseList.Remove(responseMapping); 
                            AddParameter(parameter);
                        } 
                    }
                }
            }
 
            foreach (XmlMemberMapping requestMapping in requestList) {
                SoapParameter parameter = new SoapParameter(); 
                if (RemoveByRefMapping(responseList, requestMapping)) 
                    parameter.codeFlags = CodeFlags.IsByRef;
                parameter.mapping = requestMapping; 
                AddParameter(parameter);
            }

            if (responseList.Count > 0) { 
                if (!((XmlMemberMapping) responseList[0]).CheckSpecified) {
                    ret = (XmlMemberMapping)responseList[0]; 
                    responseList.RemoveAt(0); 
                }
                foreach (XmlMemberMapping responseMapping in responseList) { 
                    SoapParameter parameter = new SoapParameter();
                    parameter.mapping = responseMapping;
                    parameter.codeFlags = CodeFlags.IsOut;
                    AddParameter(parameter); 
                }
            } 
 
            foreach (SoapParameter parameter in parameters) {
                parameter.name = identifiers.MakeUnique(CodeIdentifier.MakeValid(parameter.mapping.MemberName)); 
            }
        }

        void AddParameter(SoapParameter parameter) { 
            parameters.Add(parameter);
            if (parameter.mapping.CheckSpecified) { 
                checkSpecifiedCount++; 
            }
            if (parameter.IsByRef) { 
                inParameters.Add(parameter);
                outParameters.Add(parameter);
                if (parameter.mapping.CheckSpecified) {
                    inCheckSpecifiedCount++; 
                    outCheckSpecifiedCount++;
                } 
            } else if (parameter.IsOut) { 
                outParameters.Add(parameter);
                if (parameter.mapping.CheckSpecified) 
                    outCheckSpecifiedCount++;
            }
            else {
                inParameters.Add(parameter); 
                if (parameter.mapping.CheckSpecified)
                    inCheckSpecifiedCount++; 
            } 
        }
 
        static bool RemoveByRefMapping(ArrayList responseList, XmlMemberMapping requestMapping) {
            XmlMemberMapping responseMapping = FindMapping(responseList, requestMapping.ElementName);
            if (responseMapping == null) return false;
            if (requestMapping.TypeFullName != responseMapping.TypeFullName) return false; 
            if (requestMapping.Namespace != responseMapping.Namespace) return false;
            if (requestMapping.MemberName != responseMapping.MemberName) return false; 
            responseList.Remove(responseMapping); 
            return true;
        } 

        static void AddMappings(ArrayList mappingsList, XmlMembersMapping mappings) {
            for (int i = 0; i < mappings.Count; i++) {
                mappingsList.Add(mappings[i]); 
            }
        } 
 
        static XmlMemberMapping FindMapping(ArrayList mappingsList, string elementName) {
            foreach (XmlMemberMapping mapping in mappingsList) 
                if (mapping.ElementName == elementName)
                    return mapping;
            return null;
        } 

        internal XmlMemberMapping Return { 
            get { return ret; } 
        }
 
        internal IList Parameters {
            get { return parameters; }
        }
 
        internal IList InParameters {
            get { return inParameters; } 
        } 

        internal IList OutParameters { 
            get { return outParameters; }
        }

        internal int CheckSpecifiedCount { 
            get { return checkSpecifiedCount; }
        } 
 
        internal int InCheckSpecifiedCount {
            get { return inCheckSpecifiedCount; } 
        }

        internal int OutCheckSpecifiedCount {
            get { return outCheckSpecifiedCount; } 
        }
    } 
 
    internal class SoapParameter {
        internal CodeFlags codeFlags; 
        internal string name;
        internal XmlMemberMapping mapping;
        internal string specifiedName;
 
        internal bool IsOut {
            get { return (codeFlags & CodeFlags.IsOut) != 0; } 
        } 

        internal bool IsByRef { 
            get { return (codeFlags & CodeFlags.IsByRef) != 0; }
        }

        internal static string[] GetTypeFullNames(IList parameters, int specifiedCount, CodeDomProvider codeProvider) { 
            string[] typeFullNames = new string[parameters.Count + specifiedCount];
            GetTypeFullNames(parameters, typeFullNames, 0, specifiedCount, codeProvider); 
            return typeFullNames; 
        }
 
        internal static void GetTypeFullNames(IList parameters, string[] typeFullNames, int start, int specifiedCount, CodeDomProvider codeProvider) {
            int specified = 0;
            for (int i = 0; i < parameters.Count; i++) {
                typeFullNames[i + start + specified] = WebCodeGenerator.FullTypeName(((SoapParameter)parameters[i]).mapping, codeProvider); 
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
                    specified++; 
                    typeFullNames[i + start + specified] = typeof(bool).FullName; 
                }
            } 
        }

        internal static string[] GetNames(IList parameters, int specifiedCount) {
            string[] names = new string[parameters.Count + specifiedCount]; 
            GetNames(parameters, names, 0, specifiedCount);
            return names; 
        } 

        internal static void GetNames(IList parameters, string[] names, int start, int specifiedCount) { 
            int specified = 0;
            for (int i = 0; i < parameters.Count; i++) {
                names[i + start + specified] = ((SoapParameter)parameters[i]).name;
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) { 
                    specified++;
                    names[i + start + specified] = ((SoapParameter) parameters[i]).specifiedName; 
                } 
            }
        } 

        internal static CodeFlags[] GetCodeFlags(IList parameters, int specifiedCount) {
            CodeFlags[] codeFlags = new CodeFlags[parameters.Count + specifiedCount];
            GetCodeFlags(parameters, codeFlags, 0, specifiedCount); 
            return codeFlags;
        } 
 
        internal static void GetCodeFlags(IList parameters, CodeFlags[] codeFlags, int start, int specifiedCount) {
            int specified = 0; 
            for (int i = 0; i < parameters.Count; i++) {
                codeFlags[i + start + specified] = ((SoapParameter)parameters[i]).codeFlags;
                if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
                    specified++; 
                    codeFlags[i + start + specified] = ((SoapParameter) parameters[i]).codeFlags;
                } 
            } 
        }
    } 

    internal class GlobalSoapHeader {
        internal string fieldName;
        internal XmlTypeMapping mapping; 
        internal bool isEncoded;
    } 
 
    internal class LocalSoapHeader {
        internal SoapHeaderDirection direction; 
        internal string fieldName;
    }

    ///  
    /// 
    ///    [To be supplied.] 
    ///  
    [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
    [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")] 
    public class SoapProtocolImporter : ProtocolImporter {
        XmlSchemaImporter xmlImporter;
        XmlCodeExporter xmlExporter;
        SoapSchemaImporter soapImporter; 
        SoapCodeExporter soapExporter;
        ArrayList xmlMembers = new ArrayList(); 
        ArrayList soapMembers = new ArrayList(); 
        Hashtable headers = new Hashtable();
        Hashtable classHeaders = new Hashtable(); 
        ArrayList propertyNames = new ArrayList();
        ArrayList propertyValues = new ArrayList();
        SoapExtensionImporter[] extensions;
        SoapTransportImporter transport; 
        SoapBinding soapBinding;
        ArrayList codeClasses = new ArrayList(); 
        static TypedDataSetSchemaImporterExtension typedDataSetSchemaImporterExtension; 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        public override string ProtocolName { 
            get { return "Soap"; }
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        public SoapBinding SoapBinding {
            get { return soapBinding; } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        public SoapSchemaImporter SoapImporter {
            get { return soapImporter; }
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        public XmlSchemaImporter XmlImporter {
            get { return xmlImporter; }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        public XmlCodeExporter XmlExporter { 
            get { return xmlExporter; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public SoapCodeExporter SoapExporter {
            get { return soapExporter; } 
        }

        static TypedDataSetSchemaImporterExtension TypedDataSetSchemaImporterExtension {
            get { 
                if (typedDataSetSchemaImporterExtension == null) {
                    typedDataSetSchemaImporterExtension = new TypedDataSetSchemaImporterExtension(); 
                } 
                return typedDataSetSchemaImporterExtension;
            } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        protected override void BeginNamespace() { 
            try {
                MethodNames.Clear(); 
                ExtraCodeClasses.Clear();
                soapImporter = new SoapSchemaImporter(AbstractSchemas, ServiceImporter.CodeGenerationOptions, ImportContext);
                xmlImporter = new XmlSchemaImporter(ConcreteSchemas, ServiceImporter.CodeGenerationOptions, ServiceImporter.CodeGenerator, ImportContext);
                foreach (Type extensionType in ServiceImporter.Extensions) { 
                    xmlImporter.Extensions.Add(extensionType.FullName, extensionType);
                } 
                // use cached version of typed DataSetSchemaImporterExtension for /sharetypes feature 
                //
                xmlImporter.Extensions.Add(TypedDataSetSchemaImporterExtension); 
                xmlImporter.Extensions.Add(new DataSetSchemaImporterExtension());
                xmlExporter = new XmlCodeExporter(this.CodeNamespace, ServiceImporter.CodeCompileUnit, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
                soapExporter = new SoapCodeExporter(this.CodeNamespace, null, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
            } 
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
                    throw; 
                }
                throw new InvalidOperationException(Res.GetString(Res.InitFailed), e); 
            }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override void EndNamespace() {
            // need to preprocess all exported schemas to make sure that IXmlSerializable schemas are Merged and the resulting set is valid 
            ConcreteSchemas.Compile(null, false);

            foreach (GlobalSoapHeader soapHeader in headers.Values) {
                if (soapHeader.isEncoded) 
                    soapExporter.ExportTypeMapping(soapHeader.mapping);
                else 
                    xmlExporter.ExportTypeMapping(soapHeader.mapping); 
            }
 
            foreach (XmlMembersMapping member in xmlMembers)
                xmlExporter.ExportMembersMapping(member);

            foreach (XmlMembersMapping member in soapMembers) 
                soapExporter.ExportMembersMapping(member);
 
            // NOTE, [....], we are sharing the SoapInclude and XmlInclude attributes of the 
            // class among ALL classes generated, This is probably OK, since doing to per
            // class would probably result in the same set of includes if the user 
            // has object as a return value (meaning 'all' types are OK).
            foreach (CodeTypeDeclaration codeClass in codeClasses) {
                foreach (CodeAttributeDeclaration attribute in xmlExporter.IncludeMetadata) {
                    codeClass.CustomAttributes.Add(attribute); 
                }
                foreach (CodeAttributeDeclaration attribute in soapExporter.IncludeMetadata) { 
                    codeClass.CustomAttributes.Add(attribute); 
                }
            } 
            foreach(CodeTypeDeclaration declaration in ExtraCodeClasses) {
                this.CodeNamespace.Types.Add(declaration);
            }
            CodeGenerator.ValidateIdentifiers(CodeNamespace); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected override bool IsBindingSupported() {
            SoapBinding soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
            if (soapBinding == null || soapBinding.GetType() != typeof(SoapBinding)) return false; 

            if (GetTransport(soapBinding.Transport) == null) { 
                UnsupportedBindingWarning(Res.GetString(Res.ThereIsNoSoapTransportImporterThatUnderstands1, soapBinding.Transport)); 
                return false;
            } 

            return true;
        }
 
        internal SoapTransportImporter GetTransport(string transport) {
            foreach (Type type in WebServicesSection.Current.SoapTransportImporters) 
            { 
                SoapTransportImporter transportImporter = (SoapTransportImporter)Activator.CreateInstance(type);
                transportImporter.ImportContext = this; 
                if (transportImporter.IsSupportedTransport(transport)) return transportImporter;
            }
            return null;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override CodeTypeDeclaration BeginClass() {
            MethodNames.Clear();

            soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding)); 
            transport = GetTransport(soapBinding.Transport);
 
            Type[] requiredTypes = new Type[] { typeof(SoapDocumentMethodAttribute), typeof(XmlAttributeAttribute), typeof(WebService), typeof(Object), typeof(DebuggerStepThroughAttribute), typeof(DesignerCategoryAttribute) }; 
            WebCodeGenerator.AddImports(this.CodeNamespace, WebCodeGenerator.GetNamespacesForTypes(requiredTypes));
            CodeFlags flags = 0; 
            if (Style == ServiceDescriptionImportStyle.Server)
                flags = CodeFlags.IsAbstract;
            else if (Style == ServiceDescriptionImportStyle.ServerInterface)
                flags = CodeFlags.IsInterface; 
            CodeTypeDeclaration codeClass = WebCodeGenerator.CreateClass(this.ClassName, null,
                new string[0], null, CodeFlags.IsPublic | flags, 
                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)); 

            codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 
            if (Style == ServiceDescriptionImportStyle.Client) {
                codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DebuggerStepThroughAttribute).FullName));
                codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DesignerCategoryAttribute).FullName, new CodeAttributeArgument[] {new CodeAttributeArgument(new CodePrimitiveExpression("code"))}));
            } 
            else if (Style == ServiceDescriptionImportStyle.Server) {
                CodeAttributeDeclaration webService = new CodeAttributeDeclaration(typeof(WebServiceAttribute).FullName); 
                string targetNs = Service != null ? Service.ServiceDescription.TargetNamespace : Binding.ServiceDescription.TargetNamespace; 
                webService.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(targetNs)));
                codeClass.CustomAttributes.Add(webService); 
            }

            CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(typeof(WebServiceBindingAttribute).FullName);
            attribute.Arguments.Add(new CodeAttributeArgument("Name", new CodePrimitiveExpression(XmlConvert.DecodeName(Binding.Name)))); 
            attribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(Binding.ServiceDescription.TargetNamespace)));
 
            codeClass.CustomAttributes.Add(attribute); 

            codeClasses.Add(codeClass); 
            classHeaders.Clear();
            return codeClass;
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        protected override void EndClass() { 
            if (transport != null)
                transport.ImportClass();
            soapBinding = null;
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        protected override bool IsOperationFlowSupported(OperationFlow flow) {
            return flow == OperationFlow.OneWay || flow == OperationFlow.RequestResponse;
        }
 
        void BeginMetadata() {
            propertyNames.Clear(); 
            propertyValues.Clear(); 
        }
 
        bool MetadataPropertiesAdded {
            get { return propertyNames.Count > 0; }
        }
 
        void AddMetadataProperty(string name, object value) {
            AddMetadataProperty(name, new CodePrimitiveExpression(value)); 
        } 

        void AddMetadataProperty(string name, CodeExpression expr) { 
            propertyNames.Add(name);
            propertyValues.Add(expr);
        }
 
        void EndMetadata(CodeAttributeDeclarationCollection metadata, Type attributeType, string parameter) {
            CodeExpression[] parameters; 
            if (parameter == null) { 
                parameters = new CodeExpression[0];
            } 
            else {
                parameters = new CodeExpression[1] { new CodePrimitiveExpression(parameter) };
            }
            WebCodeGenerator.AddCustomAttribute(metadata, attributeType, parameters, 
                                  (string[])propertyNames.ToArray(typeof(string)),
                                  (CodeExpression[])propertyValues.ToArray(typeof(CodeExpression))); 
        } 

        void GenerateExtensionMetadata(CodeAttributeDeclarationCollection metadata) { 
            if (extensions == null) {
                TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionImporterTypes;
                extensions = new SoapExtensionImporter[extensionTypes.Count];
                for (int i = 0; i < extensions.Length; i++) { 
                    SoapExtensionImporter extension = (SoapExtensionImporter)Activator.CreateInstance(extensionTypes[i].Type);
                    extension.ImportContext = this; 
                    extensions[i] = extension; 
                }
            } 
            foreach (SoapExtensionImporter extension in extensions) {
                extension.ImportMethod(metadata);
            }
        } 

        void PrepareHeaders(MessageBinding messageBinding) { 
            // By default, map all headers to properties on the generated class 
            // ExtensionImporters can modify this behavior by clearing the flag
            SoapHeaderBinding[] headers = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding)); 
            foreach (SoapHeaderBinding header in headers) {
                header.MapToProperty = true;
            }
        } 

        void GenerateHeaders(CodeAttributeDeclarationCollection metadata, SoapBindingUse use, bool rpc, MessageBinding requestMessage, MessageBinding responseMessage) { 
            Hashtable localHeaders = new Hashtable(); 

            for (int i = 0; i < 2; ++ i) { 
                MessageBinding messageBinding;
                SoapHeaderDirection direction;
                if (i == 0) {
                    messageBinding = requestMessage; 
                    direction = SoapHeaderDirection.In;
                } 
                else if (responseMessage != null) { 
                    messageBinding = responseMessage;
                    direction = SoapHeaderDirection.Out; 
                }
                else
                    continue;
 
                SoapHeaderBinding[] headerBindings = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
                foreach (SoapHeaderBinding header in headerBindings) { 
                    // Skip headers which should not be mapped to properties (extension importers can control this) 
                    if (!header.MapToProperty) continue;
 
                    if (use != header.Use) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionHeaderAndBodyUseMismatch));
                    if (use == SoapBindingUse.Encoded && !IsSoapEncodingPresent(header.Encoding) )
                        throw new InvalidOperationException(Res.GetString(Res.WebUnknownEncodingStyle, header.Encoding));
 
                    Message message = ServiceDescriptions.GetMessage(header.Message);
                    if (message == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessage2, header.Message.Name, header.Message.Namespace)); 
 
                    MessagePart part = message.FindPartByName(header.Part);
                    if (part == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessagePartForMessageFromNamespace3, part.Name, header.Message.Name, header.Message.Namespace)); 

                    XmlTypeMapping mapping;
                    string key;
                    if (use == SoapBindingUse.Encoded) { 
                        if (part.Type.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartTypeRequired, part.Name, header.Message.Name, header.Message.Namespace));
                        if (!part.Element.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartElementWarning, part.Name, header.Message.Name, header.Message.Namespace)); 
                        mapping = soapImporter.ImportDerivedTypeMapping(part.Type, typeof(SoapHeader), true); 
                        key = "type=" + part.Type.ToString();
                    } 
                    else {
                        if (part.Element.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartElementRequired, part.Name, header.Message.Name, header.Message.Namespace));
                        if (!part.Type.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartTypeWarning, part.Name, header.Message.Name, header.Message.Namespace));
                        mapping = xmlImporter.ImportDerivedTypeMapping(part.Element, typeof(SoapHeader), true); 
                        key = "element=" + part.Element.ToString();
                    } 
                    LocalSoapHeader localHeader = (LocalSoapHeader)localHeaders[key]; 
                    if (localHeader == null) {
                        GlobalSoapHeader globalHeader = (GlobalSoapHeader)classHeaders[key]; 
                        if (globalHeader == null) {
                            globalHeader = new GlobalSoapHeader();
                            globalHeader.isEncoded = use == SoapBindingUse.Encoded;
                            string fieldName = CodeIdentifier.MakeValid(mapping.ElementName); 
                            if (fieldName == mapping.TypeName) fieldName += "Value";
                            fieldName = MethodNames.AddUnique(fieldName, mapping); 
                            globalHeader.fieldName = fieldName; 
                            WebCodeGenerator.AddMember(CodeTypeDeclaration, mapping.TypeFullName, globalHeader.fieldName, null, null, CodeFlags.IsPublic, ServiceImporter.CodeGenerationOptions);
                            globalHeader.mapping = mapping; 
                            classHeaders.Add(key, globalHeader);
                            if (headers[key] == null)
                                headers.Add(key, globalHeader);
                        } 

                        localHeader = new  LocalSoapHeader(); 
                        localHeader.fieldName = globalHeader.fieldName; 
                        localHeader.direction = direction;
                        localHeaders.Add(key, localHeader); 
                    }
                    else {
                        if (localHeader.direction != direction)
                            localHeader.direction = SoapHeaderDirection.InOut; 
                    }
                } 
            } 

            foreach (LocalSoapHeader soapHeader in localHeaders.Values) { 
                BeginMetadata();
                if (soapHeader.direction == SoapHeaderDirection.Out) {
                    AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.Out.ToString()));
                } 
                else if (soapHeader.direction == SoapHeaderDirection.InOut) {
                    AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.InOut.ToString())); 
                } 

                EndMetadata(metadata, typeof(SoapHeaderAttribute), soapHeader.fieldName); 
            }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected override CodeMemberMethod GenerateMethod() {
            Message requestMessage; 
            Message responseMessage;
            string[] parameterOrder;
            SoapBodyBinding soapRequestBinding;
            SoapBodyBinding soapResponseBinding; 
            MessageBinding requestBinding;
            MessageBinding responseBinding; 
 
            SoapOperationBinding soapOperationBinding = (SoapOperationBinding)this.OperationBinding.Extensions.Find(typeof(SoapOperationBinding));
            if (soapOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingSoapOperationBinding0)); 

            SoapBindingStyle soapBindingStyle = soapOperationBinding.Style;
            if (soapBindingStyle == SoapBindingStyle.Default)
                soapBindingStyle = SoapBinding.Style; 
            if (soapBindingStyle == SoapBindingStyle.Default)
                soapBindingStyle = SoapBindingStyle.Document; 
 
            parameterOrder = this.Operation.ParameterOrder;
 
            requestMessage = this.InputMessage;
            requestBinding = this.OperationBinding.Input;
            soapRequestBinding = (SoapBodyBinding)this.OperationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
            if (soapRequestBinding == null) { 
                UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyInputBinding0));
                return null; 
            } 

            if (this.Operation.Messages.Output != null) { 
                responseMessage = this.OutputMessage;
                responseBinding = this.OperationBinding.Output;
                soapResponseBinding = (SoapBodyBinding)this.OperationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
                if (soapResponseBinding == null) { 
                    UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyOutputBinding0));
                    return null; 
                } 
            }
            else { 
                responseMessage = null;
                responseBinding = null;
                soapResponseBinding = null;
            } 

            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection(); 
 
            PrepareHeaders(requestBinding);
            if (responseBinding != null) PrepareHeaders(responseBinding); 

            string requestMessageName;
            string responseMessageName = null;
 
            requestMessageName = !String.IsNullOrEmpty(requestBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? requestBinding.Name : this.Operation.Name; // per WSDL 1.1 sec 3.5
            requestMessageName = XmlConvert.DecodeName(requestMessageName); 
 
            if (responseBinding != null) {
                responseMessageName = !String.IsNullOrEmpty(responseBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? responseBinding.Name : this.Operation.Name + "Response"; // per WSDL 1.1 sec 3.5 
                responseMessageName = XmlConvert.DecodeName(responseMessageName);
            }

            GenerateExtensionMetadata(metadata); 
            GenerateHeaders(metadata, soapRequestBinding.Use, soapBindingStyle == SoapBindingStyle.Rpc, requestBinding, responseBinding);
 
            MessagePart[] requestParts = GetMessageParts(requestMessage, soapRequestBinding); 
            bool hasWrapper;
            if (!CheckMessageStyles(MethodName, requestParts, soapRequestBinding, soapBindingStyle, out hasWrapper)) 
                return null;

            MessagePart[] responseParts = null;
            if (responseMessage != null) { 
                responseParts = GetMessageParts(responseMessage, soapResponseBinding);
                bool responseHasWrapper; 
                if (!CheckMessageStyles(MethodName, responseParts, soapResponseBinding, soapBindingStyle, out responseHasWrapper)) 
                    return null;
 
                // since we're using a potentially inaccurate heuristic to determine whether there's a wrapper,
                // if we disagree about the request and response we should assume there isn't a wrapper.
                if (hasWrapper != responseHasWrapper)
                    hasWrapper = false; 
            }
 
            bool wrapperNamesMatter = (soapBindingStyle != SoapBindingStyle.Rpc && hasWrapper) || (soapRequestBinding.Use == SoapBindingUse.Literal && soapBindingStyle == SoapBindingStyle.Rpc); 

            XmlMembersMapping request = ImportMessage(requestMessageName, requestParts, soapRequestBinding, soapBindingStyle, hasWrapper); 
            if (request == null) return null;

            XmlMembersMapping response = null;
 
            if (responseMessage != null) {
                response = ImportMessage(responseMessageName, responseParts, soapResponseBinding, soapBindingStyle, hasWrapper); 
                if (response == null) return null; 
            }
 
            string methodName = CodeIdentifier.MakeValid(XmlConvert.DecodeName(this.Operation.Name));
            if (ClassName == methodName) {
                methodName = "Call" + methodName;
            } 
            string uniqueMethodName = MethodNames.AddUnique(CodeIdentifier.MakeValid(XmlConvert.DecodeName(methodName)), this.Operation);
            bool differentNames = methodName != uniqueMethodName; 
 
            CodeIdentifiers localIdentifiers = new CodeIdentifiers(false);
            localIdentifiers.AddReserved(uniqueMethodName); 

            SoapParameters parameters = new SoapParameters(request, response, parameterOrder, MethodNames);

            foreach (SoapParameter param in parameters.Parameters) { 
                if ((param.IsOut || param.IsByRef) && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReferenceParameters)) {
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReferenceParameters, ServiceImporter.CodeGenerator.GetType().Name)); 
                    return null; 
                }
                param.name = localIdentifiers.AddUnique(param.name, null); 
                if (param.mapping.CheckSpecified)
                    param.specifiedName = localIdentifiers.AddUnique(param.name + "Specified", null);
            }
 
            if (!(Style == ServiceDescriptionImportStyle.Client) || differentNames) {
                BeginMetadata(); 
                if (differentNames) AddMetadataProperty("MessageName", uniqueMethodName); 
                EndMetadata(metadata, typeof(WebMethodAttribute), null);
            } 

            BeginMetadata();
            if (wrapperNamesMatter && request.ElementName.Length > 0 && request.ElementName != uniqueMethodName)
                AddMetadataProperty("RequestElementName", request.ElementName); 
            if (request.Namespace != null)
                AddMetadataProperty("RequestNamespace", request.Namespace); 
            if (response == null) { 
                AddMetadataProperty("OneWay", true);
            } 
            else {
                if (wrapperNamesMatter && response.ElementName.Length > 0 && response.ElementName != (uniqueMethodName + "Response"))
                    AddMetadataProperty("ResponseElementName", response.ElementName);
                if (response.Namespace != null) 
                    AddMetadataProperty("ResponseNamespace", response.Namespace);
            } 
 
            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                if (soapRequestBinding.Use != SoapBindingUse.Encoded) { 
                    AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
                }
                EndMetadata(metadata, typeof(SoapRpcMethodAttribute), soapOperationBinding.SoapAction);
            } 
            else {
                AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G"))); 
                AddMetadataProperty("ParameterStyle", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapParameterStyle).FullName), Enum.Format(typeof(SoapParameterStyle), hasWrapper ? SoapParameterStyle.Wrapped : SoapParameterStyle.Bare, "G"))); 
                EndMetadata(metadata, typeof(SoapDocumentMethodAttribute), soapOperationBinding.SoapAction);
            } 
            IsEncodedBinding = IsEncodedBinding || (soapRequestBinding.Use == SoapBindingUse.Encoded);

            CodeAttributeDeclarationCollection[] paramsMetadata = new CodeAttributeDeclarationCollection[parameters.Parameters.Count + parameters.CheckSpecifiedCount];
            int j = 0; 
            CodeAttributeDeclaration ignoreAttribute = new CodeAttributeDeclaration(typeof(XmlIgnoreAttribute).FullName);
            foreach (SoapParameter parameter in parameters.Parameters) { 
                paramsMetadata[j] = new CodeAttributeDeclarationCollection(); 
                if (soapRequestBinding.Use == SoapBindingUse.Encoded)
                    soapExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, parameter.name != parameter.mapping.MemberName); 
                else {
                    string ns = soapBindingStyle == SoapBindingStyle.Rpc ? parameter.mapping.Namespace : parameter.IsOut ? response.Namespace : request.Namespace;
                    bool forceUseMemberName = parameter.name != parameter.mapping.MemberName;
                    xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping,  ns, forceUseMemberName); 
                    if (parameter.mapping.CheckSpecified) {
                        j++; 
                        paramsMetadata[j] = new CodeAttributeDeclarationCollection(); 
                        xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, parameter.specifiedName != parameter.mapping.MemberName + "Specified");
                        paramsMetadata[j].Add(ignoreAttribute); 
                    }
                }
                if (paramsMetadata[j].Count > 0  && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ParameterAttributes)) {
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportParameterAttributes, ServiceImporter.CodeGenerator.GetType().Name)); 
                    return null;
                } 
                j++; 
            }
 
            CodeFlags[] parameterFlags = SoapParameter.GetCodeFlags(parameters.Parameters, parameters.CheckSpecifiedCount);
            string[] parameterTypes = SoapParameter.GetTypeFullNames(parameters.Parameters, parameters.CheckSpecifiedCount, ServiceImporter.CodeGenerator);
            string returnType = parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
 
            CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, methodName,
                                        parameterFlags, 
                                        parameterTypes, 
                                        SoapParameter.GetNames(parameters.Parameters, parameters.CheckSpecifiedCount),
                                        paramsMetadata, 
                                        returnType,
                                        metadata,
                                        CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract));
 
            mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
 
            if (parameters.Return != null) { 
                if (soapRequestBinding.Use == SoapBindingUse.Encoded)
                    soapExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, parameters.Return.ElementName != uniqueMethodName + "Result"); 
                else
                    xmlExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, response.Namespace, parameters.Return.ElementName != uniqueMethodName + "Result");

                if (mainCodeMethod.ReturnTypeCustomAttributes.Count != 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReturnTypeAttributes)) { 
                    UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReturnTypeAttributes, ServiceImporter.CodeGenerator.GetType().Name));
                    return null; 
                } 
            }
 
            string resultsName = localIdentifiers.MakeUnique("results");

            if (Style == ServiceDescriptionImportStyle.Client) {
                bool oldAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateOldAsync) != 0; 
                bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) && 
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates); 
                CodeExpression[] invokeParams = new CodeExpression[2];
                CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount); 
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams);
                WriteReturnMappings(mainCodeMethod, invoke, parameters, resultsName);

                if (oldAsync) { 
                    int inCount = parameters.InParameters.Count + parameters.InCheckSpecifiedCount;
 
                    string[] asyncParameterTypes = new string[inCount + 2]; 
                    SoapParameter.GetTypeFullNames(parameters.InParameters, asyncParameterTypes, 0, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                    asyncParameterTypes[inCount] = typeof(AsyncCallback).FullName; 
                    asyncParameterTypes[inCount + 1] = typeof(object).FullName;

                    string[] asyncParameterNames = new string[inCount + 2];
                    SoapParameter.GetNames(parameters.InParameters, asyncParameterNames, 0, parameters.InCheckSpecifiedCount); 
                    asyncParameterNames[inCount] = "callback";
                    asyncParameterNames[inCount + 1] = "asyncState"; 
 
                    CodeFlags[] asyncParameterFlags = new CodeFlags[inCount + 2];
 
                    CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + uniqueMethodName,
                        asyncParameterFlags,
                        asyncParameterTypes,
                        asyncParameterNames, 
                        typeof(IAsyncResult).FullName,
                        null, 
                        CodeFlags.IsPublic); 

                    beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    invokeParams = new CodeExpression[4];
                    CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
                    invokeParams[2] = new CodeArgumentReferenceExpression("callback"); 
                    invokeParams[3] = new CodeArgumentReferenceExpression("asyncState");
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams); 
                    beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
 
                    int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
                    string[] asyncReturnTypes = new string[outCount + 1];
                    SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                    asyncReturnTypes[0] = typeof(IAsyncResult).FullName; 

                    string[] asyncReturnNames = new string[outCount + 1]; 
                    SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount); 
                    asyncReturnNames[0] = "asyncResult";
 
                    CodeFlags[] asyncReturnFlags = new CodeFlags[outCount + 1];
                    for (int i = 0; i < outCount; i++)
                        asyncReturnFlags[i + 1] = CodeFlags.IsOut;
 
                    CodeMemberMethod codeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + uniqueMethodName,
                        asyncReturnFlags, 
                        asyncReturnTypes, 
                        asyncReturnNames,
                        parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), 
                        null,
                        CodeFlags.IsPublic);

                    codeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    CodeExpression invokeParam = new CodeArgumentReferenceExpression("asyncResult"); 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { invokeParam }); 

                    WriteReturnMappings(codeMethod, invoke, parameters, resultsName); 
                }

                // new RAD Async pattern
                if (newAsync) { 
                    string methodKey = MethodSignature(uniqueMethodName, returnType, parameterFlags, parameterTypes);
                    DelegateInfo delegateInfo = (DelegateInfo)ExportContext[methodKey]; 
                    if (delegateInfo == null) { 
                        string handlerType = ClassNames.AddUnique(uniqueMethodName + "CompletedEventHandler", uniqueMethodName);
                        string handlerArgs = ClassNames.AddUnique(uniqueMethodName + "CompletedEventArgs", uniqueMethodName); 
                        delegateInfo = new DelegateInfo(handlerType, handlerArgs);
                    }
                    string handlerName = MethodNames.AddUnique(uniqueMethodName + "Completed", uniqueMethodName);
                    string asyncName = MethodNames.AddUnique(uniqueMethodName + "Async", uniqueMethodName); 
                    string callbackMember = MethodNames.AddUnique(uniqueMethodName + "OperationCompleted", uniqueMethodName);
                    string callbackName = MethodNames.AddUnique("On" + uniqueMethodName + "OperationCompleted", uniqueMethodName); 
 
                    // public event xxxCompletedEventHandler xxxCompleted;
                    WebCodeGenerator.AddEvent(this.CodeTypeDeclaration.Members, delegateInfo.handlerType, handlerName); 

                    // private SendOrPostCallback xxxOperationCompleted;
                    WebCodeGenerator.AddCallbackDeclaration(this.CodeTypeDeclaration.Members, callbackMember);
 
                    // create the pair of xxxAsync methods
                    string[] inParamNames = SoapParameter.GetNames(parameters.InParameters, parameters.InCheckSpecifiedCount); 
                    string userState = UniqueName("userState", inParamNames); 
                    CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName,
                        SoapParameter.GetTypeFullNames(parameters.InParameters, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator), inParamNames, callbackMember, callbackName, userState); 

                    // Generate InvokeAsync call
                    invokeParams = new CodeExpression[4];
                    CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount); 
                    invokeParams[2] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember);
                    invokeParams[3] = new CodeArgumentReferenceExpression(userState); 
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams);
                    asyncCodeMethod.Statements.Add(invoke); 

                    //  private void On_xxx_OperationCompleted(object arg) {..}
                    bool methodHasOutParameters = parameters.Return != null || parameters.OutParameters.Count > 0;
                    WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasOutParameters); 

                    if (ExportContext[methodKey] == null) { 
                        // public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args); 
                        WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasOutParameters ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName);
 
                        // Create strongly-typed Args class
                        if (methodHasOutParameters) {
                            int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
                            string[] asyncReturnTypes = new string[outCount + 1]; 
                            SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
                            asyncReturnTypes[0] = parameters.Return == null ? null : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator); 
 
                            string[] asyncReturnNames = new string[outCount + 1];
                            SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount); 
                            asyncReturnNames[0] = parameters.Return == null ? null : "Result";
                            ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, asyncReturnTypes, asyncReturnNames, ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
                        }
                        ExportContext[methodKey] = delegateInfo; 
                    }
                } 
            } 
            return mainCodeMethod;
        } 

        void WriteReturnMappings(CodeMemberMethod codeMethod, CodeExpression invoke, SoapParameters parameters, string resultsName) {
            if (parameters.Return == null && parameters.OutParameters.Count == 0) {
                codeMethod.Statements.Add(new CodeExpressionStatement(invoke)); 
            }
            else { 
                codeMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), resultsName, invoke)); 

                int count = parameters.Return == null ? 0 : 1; 
                for (int i = 0; i < parameters.OutParameters.Count; i++) {
                    SoapParameter parameter = (SoapParameter)parameters.OutParameters[i];
                    CodeExpression target = new CodeArgumentReferenceExpression(parameter.name);
                    CodeExpression value = new CodeArrayIndexerExpression(); 
                    ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                    ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++)); 
                    value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameter.mapping, ServiceImporter.CodeGenerator), value); 
                    codeMethod.Statements.Add(new CodeAssignStatement(target, value));
                    if (parameter.mapping.CheckSpecified) { 
                        target = new CodeArgumentReferenceExpression(parameter.name + "Specified");
                        value = new CodeArrayIndexerExpression();
                        ((CodeArrayIndexerExpression) value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                        ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++)); 
                        value = new CodeCastExpression(typeof(bool).FullName, value);
                        codeMethod.Statements.Add(new CodeAssignStatement(target, value)); 
                    } 
                }
 
                if (parameters.Return != null) {
                    CodeExpression value = new CodeArrayIndexerExpression();
                    ((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
                    ((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(0)); 
                    value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), value);
                    codeMethod.Statements.Add(new CodeMethodReturnStatement(value)); 
                } 
            }
        } 

        void CreateInvokeParams(CodeExpression[] invokeParams, string methodName, IList parameters, int checkSpecifiedCount) {
            invokeParams[0] = new CodePrimitiveExpression(methodName);
 
            CodeExpression[] values = new CodeExpression[parameters.Count + checkSpecifiedCount];
            int value = 0; 
            for (int i = 0; i < parameters.Count; i++) { 
                SoapParameter parameter = (SoapParameter)parameters[i];
                values[value++] = new CodeArgumentReferenceExpression(parameter.name); 
                if (parameter.mapping.CheckSpecified)
                    values[value++] = new CodeArgumentReferenceExpression(parameter.specifiedName);
            }
            invokeParams[1] = new CodeArrayCreateExpression(typeof(object).FullName, values); 
        }
 
        // returns false if we didn't like the message -- otherwise caller is safe to use body binding and binding style 
        bool CheckMessageStyles(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, out bool hasWrapper) {
            hasWrapper = false; 
            if (soapBodyBinding.Use == SoapBindingUse.Default) {
                soapBodyBinding.Use = SoapBindingUse.Literal;
            }
            if (soapBodyBinding.Use == SoapBindingUse.Literal) { 
                if (soapBindingStyle == SoapBindingStyle.Rpc) {
                    foreach (MessagePart part in parts) { 
                        if (!part.Element.IsEmpty) { 
                            UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInRpcUseLiteralMessageMustSpecify0));
                            return false; 
                        }
                    }
                    return true;
                } 
                if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
                    // special top-level any case 
                    if (!parts[0].Element.IsEmpty) { 
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
                        return false; 
                    }
                    XmlMembersMapping membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
                    if (membersMapping == null) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIsAny, parts[0].Type.Name, parts[0].Type.Namespace)); 
                        return false;
                    } 
                    return true; 
                }
                else { 
                    foreach (MessagePart part in parts) {
                        if (!part.Type.IsEmpty) {
                            UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
                            return false; 
                        }
                        if (part.Element.IsEmpty) { 
                            UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAUseLiteralMessageMustSpecify0)); 
                            return false;
                        } 
                    }
                }
            }
            else if (soapBodyBinding.Use == SoapBindingUse.Encoded) { 
                if (!IsSoapEncodingPresent(soapBodyBinding.Encoding)) {
                    UnsupportedOperationBindingWarning(Res.GetString(Res.TheEncodingIsNotSupported1, soapBodyBinding.Encoding)); 
                    return false; 
                }
                foreach (MessagePart part in parts) { 
                    if (!part.Element.IsEmpty) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingAnElementForUseEncodedMessageParts0));
                        return false;
                    } 
                    if (part.Type.IsEmpty) {
                        UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAnUseEncodedMessageMustSpecify0)); 
                        return false; 
                    }
                } 
            }

            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                return true; 
            }
            else if (soapBindingStyle == SoapBindingStyle.Document) { 
                // NOTE, [....].  WSDL doesn't really let us figure out whether a document is 
                // in fact a struct containing parameters, so we apply a little heuristic here
                // in order to produce the appropriate programming model. 
                hasWrapper = (parts.Length == 1 && string.Compare(parts[0].Name, "parameters", StringComparison.Ordinal) == 0);
                return true;
            }
            return false; 
        }
 
        ///  
        ///
        protected virtual bool IsSoapEncodingPresent(string uriList) { 
            int iStart = 0;
            do {
                iStart = uriList.IndexOf(Soap.Encoding, iStart, StringComparison.Ordinal);
                if (iStart < 0) 
                    return false;
                int iEnd = iStart + Soap.Encoding.Length; 
                if (iStart == 0 || uriList[iStart-1] == ' ') 
                    if (iEnd == uriList.Length || uriList[iEnd] == ' ')
                        return true; 
                iStart = iEnd;
            } while (iStart < uriList.Length);
            return false;
        } 

        MessagePart[] GetMessageParts(Message message, SoapBodyBinding soapBodyBinding) { 
            MessagePart[] parts; 
            if (soapBodyBinding.Parts == null) {
                parts = new MessagePart[message.Parts.Count]; 
                message.Parts.CopyTo(parts, 0);
            }
            else {
                parts = message.FindPartsByName(soapBodyBinding.Parts); 
            }
            return parts; 
        } 

        XmlMembersMapping ImportMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) { 
            if (soapBodyBinding.Use == SoapBindingUse.Encoded)
                return ImportEncodedMessage(messageName, parts, soapBodyBinding, wrapped);
            else
                return ImportLiteralMessage(messageName, parts, soapBodyBinding, soapBindingStyle, wrapped); 
        }
 
        XmlMembersMapping ImportEncodedMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, bool wrapped) { 
            XmlMembersMapping membersMapping;
            if (wrapped) { 
                SoapSchemaMember schemaMember = new SoapSchemaMember();
                schemaMember.MemberName = parts[0].Name;
                schemaMember.MemberType = parts[0].Type;
                membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMember); 
            }
            else { 
                SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length]; 
                for (int i = 0; i < schemaMembers.Length; i++) {
                    MessagePart part = parts[i]; 
                    SoapSchemaMember schemaMember = new SoapSchemaMember();
                    schemaMember.MemberName = part.Name;
                    schemaMember.MemberType = part.Type;
                    schemaMembers[i] = schemaMember; 
                }
                membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers); 
            } 
            soapMembers.Add(membersMapping);
            return membersMapping; 
        }

        XmlMembersMapping ImportLiteralMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
            XmlMembersMapping membersMapping; 
            if (soapBindingStyle == SoapBindingStyle.Rpc) {
                SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length]; 
                for (int i = 0; i < schemaMembers.Length; i++) { 
                    MessagePart part = parts[i];
                    SoapSchemaMember schemaMember = new SoapSchemaMember(); 
                    schemaMember.MemberName = part.Name;
                    schemaMember.MemberType = part.Type;
                    schemaMembers[i] = schemaMember;
                } 
                membersMapping = xmlImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
            } 
            else if (wrapped) { 
                membersMapping = xmlImporter.ImportMembersMapping(parts[0].Element);
            } 
            else {
                if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
                    // special case for  at root
                    // we know this will work because we tried it earlier in CheckMessageStyles. 
                    membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
                    xmlMembers.Add(membersMapping); 
                    return membersMapping; 
                }
                XmlQualifiedName[] names = new XmlQualifiedName[parts.Length]; 
                for (int i = 0; i < parts.Length; i++)
                    names[i] = parts[i].Element;
                membersMapping = xmlImporter.ImportMembersMapping(names);
            } 
            xmlMembers.Add(membersMapping);
            return membersMapping; 
        } 
    }
} 

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