HttpProtocolImporter.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 / HttpProtocolImporter.cs / 1305376 / HttpProtocolImporter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Web.Services.Description {
 
    using System.Web.Services; 
    using System.Web.Services.Protocols;
    using System.Xml; 
    using System.Xml.Serialization;
    using System.Xml.Schema;
    using System.Collections;
    using System; 
    using System.Reflection;
    using System.CodeDom; 
    using System.CodeDom.Compiler; 
    using System.Web.Services.Configuration;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Threading;
    using System.EnterpriseServices;
 
    //
    internal class HttpMethodInfo { 
        internal MimeParameterCollection UrlParameters; 
        internal MimeParameterCollection MimeParameters;
        internal MimeReturn MimeReturn; 
        internal string Name;
        internal string Href;
    }
 
    internal abstract class HttpProtocolImporter : ProtocolImporter {
        MimeImporter[] importers; 
        ArrayList[] importedParameters; 
        ArrayList[] importedReturns;
        bool hasInputPayload; 
        ArrayList codeClasses = new ArrayList();

        protected HttpProtocolImporter(bool hasInputPayload) {
            Type[] importerTypes = WebServicesSection.Current.MimeImporterTypes; 
            importers = new MimeImporter[importerTypes.Length];
            importedParameters = new ArrayList[importerTypes.Length]; 
            importedReturns = new ArrayList[importerTypes.Length]; 
            for (int i = 0; i < importers.Length; i++) {
                MimeImporter importer = (MimeImporter)Activator.CreateInstance(importerTypes[i]); 
                importer.ImportContext = this;
                importedParameters[i] = new ArrayList();
                importedReturns[i] = new ArrayList();
                importers[i] = importer; 
            }
            this.hasInputPayload = hasInputPayload; 
        } 

        // 
        MimeParameterCollection ImportMimeParameters() {
            for (int i = 0; i < importers.Length; i++) {
                MimeParameterCollection importedParameters = importers[i].ImportParameters();
                if (importedParameters != null) { 
                    this.importedParameters[i].Add(importedParameters);
                    return importedParameters; 
                } 
            }
            return null; 
        }

        MimeReturn ImportMimeReturn() {
            MimeReturn importedReturn; 
            if (OperationBinding.Output.Extensions.Count == 0) {
                importedReturn = new MimeReturn(); 
                importedReturn.TypeName = typeof(void).FullName; 
                return importedReturn;
            } 
            for (int i = 0; i < importers.Length; i++) {
                importedReturn = importers[i].ImportReturn();
                if (importedReturn != null) {
                    this.importedReturns[i].Add(importedReturn); 
                    return importedReturn;
                } 
            } 
            return null;
        } 

        MimeParameterCollection ImportUrlParameters() {
            //
            HttpUrlEncodedBinding httpUrlEncodedBinding = (HttpUrlEncodedBinding)OperationBinding.Input.Extensions.Find(typeof(HttpUrlEncodedBinding)); 
            if (httpUrlEncodedBinding == null) return new MimeParameterCollection();
            return ImportStringParametersMessage(); 
        } 

        internal MimeParameterCollection ImportStringParametersMessage() { 
            MimeParameterCollection parameters = new MimeParameterCollection();
            foreach (MessagePart part in InputMessage.Parts) {
                MimeParameter parameter = ImportUrlParameter(part);
                if (parameter == null) return null; 
                parameters.Add(parameter);
            } 
            return parameters; 
        }
 
        MimeParameter ImportUrlParameter(MessagePart part) {
            //
            MimeParameter parameter = new MimeParameter();
            parameter.Name = CodeIdentifier.MakeValid(XmlConvert.DecodeName(part.Name)); 
            parameter.TypeName = IsRepeatingParameter(part) ? typeof(string[]).FullName : typeof(string).FullName;
            return parameter; 
        } 

        bool IsRepeatingParameter(MessagePart part) { 
            XmlSchemaComplexType type = (XmlSchemaComplexType)Schemas.Find(part.Type, typeof(XmlSchemaComplexType));
            if (type == null) return false;
            if (type.ContentModel == null) return false;
            if (type.ContentModel.Content == null) throw new ArgumentException(Res.GetString(Res.Missing2, type.Name, type.ContentModel.GetType().Name), "part"); 
            if (type.ContentModel.Content is XmlSchemaComplexContentExtension) {
                return ((XmlSchemaComplexContentExtension)type.ContentModel.Content).BaseTypeName == new XmlQualifiedName(Soap.ArrayType, Soap.Encoding); 
            } 
            else if (type.ContentModel.Content is XmlSchemaComplexContentRestriction) {
                return ((XmlSchemaComplexContentRestriction)type.ContentModel.Content).BaseTypeName == new XmlQualifiedName(Soap.ArrayType, Soap.Encoding); 
            }
            return false;
        }
 
        static void AppendMetadata(CodeAttributeDeclarationCollection from, CodeAttributeDeclarationCollection to) {
            foreach (CodeAttributeDeclaration attr in from) to.Add(attr); 
        } 

        CodeMemberMethod GenerateMethod(HttpMethodInfo method) { 
            MimeParameterCollection parameters = method.MimeParameters != null ? method.MimeParameters : method.UrlParameters;

            string[] parameterTypeNames = new string[parameters.Count];
            string[] parameterNames = new string[parameters.Count]; 

            for (int i = 0; i < parameters.Count; i++) { 
                MimeParameter param = parameters[i]; 
                parameterNames[i] = param.Name;
                parameterTypeNames[i] = param.TypeName; 
            }

            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
 
            CodeExpression[] formatterTypes = new CodeExpression[2];
 
            if (method.MimeReturn.ReaderType == null) { 
                formatterTypes[0] = new CodeTypeOfExpression(typeof(NopReturnReader).FullName);
            } 
            else {
                formatterTypes[0] = new CodeTypeOfExpression(method.MimeReturn.ReaderType.FullName);
            }
 
            if (method.MimeParameters != null)
                formatterTypes[1] = new CodeTypeOfExpression(method.MimeParameters.WriterType.FullName); 
            else 
                formatterTypes[1] = new CodeTypeOfExpression(typeof(UrlParameterWriter).FullName);
 
            WebCodeGenerator.AddCustomAttribute(metadata, typeof(HttpMethodAttribute), formatterTypes, new string[0], new CodeExpression[0]);


            CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, method.Name, new CodeFlags[parameterTypeNames.Length], parameterTypeNames, parameterNames, 
                                        method.MimeReturn.TypeName, metadata,
                                        CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract)); 
 
            AppendMetadata(method.MimeReturn.Attributes, mainCodeMethod.ReturnTypeCustomAttributes);
 
            mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));

            for (int i = 0; i < parameters.Count; i++) {
                AppendMetadata(parameters[i].Attributes, mainCodeMethod.Parameters[i].CustomAttributes); 
            }
 
            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[3]; 
                CreateInvokeParams(invokeParams, method, parameterNames);
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams); 
                if (method.MimeReturn.ReaderType != null) { 
                    mainCodeMethod.Statements.Add(new CodeMethodReturnStatement(new CodeCastExpression(method.MimeReturn.TypeName, invoke)));
                } 
                else {
                    mainCodeMethod.Statements.Add(new CodeExpressionStatement(invoke));
                }
 
                metadata = new CodeAttributeDeclarationCollection();
 
                string[] asyncParameterTypeNames = new string[parameterTypeNames.Length + 2]; 
                parameterTypeNames.CopyTo(asyncParameterTypeNames, 0);
                asyncParameterTypeNames[parameterTypeNames.Length] = typeof(AsyncCallback).FullName; 
                asyncParameterTypeNames[parameterTypeNames.Length + 1] = typeof(object).FullName;

                string[] asyncParameterNames = new string[parameterNames.Length + 2];
                parameterNames.CopyTo(asyncParameterNames, 0); 
                asyncParameterNames[parameterNames.Length] = "callback";
                asyncParameterNames[parameterNames.Length + 1] = "asyncState"; 
 
                if (oldAsync) {
                    CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + method.Name, new CodeFlags[asyncParameterTypeNames.Length], 
                        asyncParameterTypeNames, asyncParameterNames,
                        typeof(IAsyncResult).FullName, metadata, CodeFlags.IsPublic);
                    beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
 
                    invokeParams = new CodeExpression[5];
                    CreateInvokeParams(invokeParams, method, parameterNames); 
 
                    invokeParams[3] = new CodeArgumentReferenceExpression( "callback");
                    invokeParams[4] = new CodeArgumentReferenceExpression( "asyncState"); 

                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams);
                    beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
 
                    CodeMemberMethod endCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + method.Name, new CodeFlags[1],
                        new string[] { typeof(IAsyncResult).FullName }, 
                        new string[] { "asyncResult" }, 
                        method.MimeReturn.TypeName, metadata, CodeFlags.IsPublic);
                    endCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    CodeExpression expr = new CodeArgumentReferenceExpression( "asyncResult");
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { expr });
                    if (method.MimeReturn.ReaderType != null) { 
                        endCodeMethod.Statements.Add(new CodeMethodReturnStatement(new CodeCastExpression(method.MimeReturn.TypeName, invoke)));
                    } 
                    else { 
                        endCodeMethod.Statements.Add(new CodeExpressionStatement(invoke));
                    } 
                }
                if (newAsync) {
                    metadata = new CodeAttributeDeclarationCollection();
                    string uniqueMethodName = method.Name; 
                    string methodKey = MethodSignature(uniqueMethodName, method.MimeReturn.TypeName, new CodeFlags[parameterTypeNames.Length], parameterTypeNames);
                    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 userState = UniqueName("userState", parameterNames); 
                    CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName, 
                        parameterTypeNames, parameterNames, callbackMember, callbackName, userState);
 
                    // Generate InvokeAsync call
                    invokeParams = new CodeExpression[5];
                    CreateInvokeParams(invokeParams, method, parameterNames);
                    invokeParams[3] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember); 
                    invokeParams[4] = new CodeArgumentReferenceExpression(userState);
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams); 
                    asyncCodeMethod.Statements.Add(invoke);
 
                    //  private void On_xxx_OperationCompleted(object arg) {..}
                    bool methodHasReturn = method.MimeReturn.ReaderType != null;
                    WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasReturn);
                    if (ExportContext[methodKey] == null) { 
                        // public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args);
                        WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasReturn ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName); 
 
                        if (methodHasReturn) {
                            ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, new string[] {method.MimeReturn.TypeName}, new string[] {"Result"}, 
                                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
                        }
                        ExportContext[methodKey] = delegateInfo;
                    } 
                }
            } 
            return mainCodeMethod; 
        }
 
        void CreateInvokeParams(CodeExpression[] invokeParams, HttpMethodInfo method, string[] parameterNames) {
            invokeParams[0] = new CodePrimitiveExpression(method.Name);

            CodeExpression left = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Url"); 
            CodeExpression right = new CodePrimitiveExpression(method.Href);
            invokeParams[1] = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.Add, right); 
 
            CodeExpression[] values = new CodeExpression[parameterNames.Length];
            for (int i = 0; i < parameterNames.Length; i++) { 
                values[i] = new CodeArgumentReferenceExpression( parameterNames[i]);
            }
            invokeParams[2] = new CodeArrayCreateExpression(typeof(object).FullName, values);
        } 

        protected override bool IsOperationFlowSupported(OperationFlow flow) { 
            return flow == OperationFlow.RequestResponse; 
        }
 
        //

        protected override CodeMemberMethod GenerateMethod() {
            HttpOperationBinding httpOperationBinding = (HttpOperationBinding)OperationBinding.Extensions.Find(typeof(HttpOperationBinding)); 
            if (httpOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingHttpOperationElement0));
 
            HttpMethodInfo method = new HttpMethodInfo(); 

            if (hasInputPayload) { 
                method.MimeParameters = ImportMimeParameters();
                if (method.MimeParameters == null) {
                    UnsupportedOperationWarning(Res.GetString(Res.NoInputMIMEFormatsWereRecognized0));
                    return null; 
                }
            } 
            else { 
                method.UrlParameters = ImportUrlParameters();
                if (method.UrlParameters == null) { 
                    UnsupportedOperationWarning(Res.GetString(Res.NoInputHTTPFormatsWereRecognized0));
                    return null;
                }
            } 
            method.MimeReturn = ImportMimeReturn();
            if (method.MimeReturn == null) { 
                UnsupportedOperationWarning(Res.GetString(Res.NoOutputMIMEFormatsWereRecognized0)); 
                return null;
            } 
            method.Name = MethodNames.AddUnique(MethodName, method);
            method.Href = httpOperationBinding.Location;
            return GenerateMethod(method);
        } 

        protected override CodeTypeDeclaration BeginClass() { 
            MethodNames.Clear(); 
            ExtraCodeClasses.Clear();
            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection(); 
            if (Style == ServiceDescriptionImportStyle.Client) {
                WebCodeGenerator.AddCustomAttribute(metadata, typeof(DebuggerStepThroughAttribute), new CodeExpression[0]);
                WebCodeGenerator.AddCustomAttribute(metadata, typeof(DesignerCategoryAttribute), new CodeExpression[] { new CodePrimitiveExpression("code") });
            } 

            Type[] requiredTypes = new Type[] { 
                typeof(SoapDocumentMethodAttribute), 
                typeof(XmlAttributeAttribute),
                typeof(WebService), 
                typeof(Object),
                typeof(DebuggerStepThroughAttribute),
                typeof(DesignerCategoryAttribute),
                typeof(TransactionOption), 
            };
            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, BaseClass.FullName,
                new string[0], metadata, CodeFlags.IsPublic | flags, 
                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes));
 
            codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

            CodeConstructor ctor = WebCodeGenerator.AddConstructor(codeClass, new string[0], new string[0], null, CodeFlags.IsPublic); 
            ctor.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));

            HttpAddressBinding httpAddressBinding = Port == null ? null : (HttpAddressBinding)Port.Extensions.Find(typeof(HttpAddressBinding));
            string url =  (httpAddressBinding != null) ? httpAddressBinding.Location : null; 
            ServiceDescription serviceDescription = Binding.ServiceDescription;
            ProtocolImporterUtil.GenerateConstructorStatements(ctor, url, serviceDescription.AppSettingUrlKey, serviceDescription.AppSettingBaseUrl, false); 
 
            codeClasses.Add(codeClass);
            return codeClass; 
        }

        protected override void EndNamespace() {
            for (int i = 0; i < importers.Length; i++) { 
                importers[i].GenerateCode((MimeReturn[])importedReturns[i].ToArray(typeof(MimeReturn)),
                                          (MimeParameterCollection[])importedParameters[i].ToArray(typeof(MimeParameterCollection))); 
            } 

            foreach (CodeTypeDeclaration codeClass in codeClasses) { 
                if (codeClass.CustomAttributes == null)
                    codeClass.CustomAttributes = new CodeAttributeDeclarationCollection();

                for (int i = 0; i < importers.Length; i++) { 
                    importers[i].AddClassMetadata(codeClass);
                } 
            } 
            foreach(CodeTypeDeclaration declaration in ExtraCodeClasses) {
                this.CodeNamespace.Types.Add(declaration); 
            }
            CodeGenerator.ValidateIdentifiers(CodeNamespace);
        }
 
        internal abstract Type BaseClass { get; }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 
namespace System.Web.Services.Description {
 
    using System.Web.Services; 
    using System.Web.Services.Protocols;
    using System.Xml; 
    using System.Xml.Serialization;
    using System.Xml.Schema;
    using System.Collections;
    using System; 
    using System.Reflection;
    using System.CodeDom; 
    using System.CodeDom.Compiler; 
    using System.Web.Services.Configuration;
    using System.Diagnostics; 
    using System.ComponentModel;
    using System.Threading;
    using System.EnterpriseServices;
 
    //
    internal class HttpMethodInfo { 
        internal MimeParameterCollection UrlParameters; 
        internal MimeParameterCollection MimeParameters;
        internal MimeReturn MimeReturn; 
        internal string Name;
        internal string Href;
    }
 
    internal abstract class HttpProtocolImporter : ProtocolImporter {
        MimeImporter[] importers; 
        ArrayList[] importedParameters; 
        ArrayList[] importedReturns;
        bool hasInputPayload; 
        ArrayList codeClasses = new ArrayList();

        protected HttpProtocolImporter(bool hasInputPayload) {
            Type[] importerTypes = WebServicesSection.Current.MimeImporterTypes; 
            importers = new MimeImporter[importerTypes.Length];
            importedParameters = new ArrayList[importerTypes.Length]; 
            importedReturns = new ArrayList[importerTypes.Length]; 
            for (int i = 0; i < importers.Length; i++) {
                MimeImporter importer = (MimeImporter)Activator.CreateInstance(importerTypes[i]); 
                importer.ImportContext = this;
                importedParameters[i] = new ArrayList();
                importedReturns[i] = new ArrayList();
                importers[i] = importer; 
            }
            this.hasInputPayload = hasInputPayload; 
        } 

        // 
        MimeParameterCollection ImportMimeParameters() {
            for (int i = 0; i < importers.Length; i++) {
                MimeParameterCollection importedParameters = importers[i].ImportParameters();
                if (importedParameters != null) { 
                    this.importedParameters[i].Add(importedParameters);
                    return importedParameters; 
                } 
            }
            return null; 
        }

        MimeReturn ImportMimeReturn() {
            MimeReturn importedReturn; 
            if (OperationBinding.Output.Extensions.Count == 0) {
                importedReturn = new MimeReturn(); 
                importedReturn.TypeName = typeof(void).FullName; 
                return importedReturn;
            } 
            for (int i = 0; i < importers.Length; i++) {
                importedReturn = importers[i].ImportReturn();
                if (importedReturn != null) {
                    this.importedReturns[i].Add(importedReturn); 
                    return importedReturn;
                } 
            } 
            return null;
        } 

        MimeParameterCollection ImportUrlParameters() {
            //
            HttpUrlEncodedBinding httpUrlEncodedBinding = (HttpUrlEncodedBinding)OperationBinding.Input.Extensions.Find(typeof(HttpUrlEncodedBinding)); 
            if (httpUrlEncodedBinding == null) return new MimeParameterCollection();
            return ImportStringParametersMessage(); 
        } 

        internal MimeParameterCollection ImportStringParametersMessage() { 
            MimeParameterCollection parameters = new MimeParameterCollection();
            foreach (MessagePart part in InputMessage.Parts) {
                MimeParameter parameter = ImportUrlParameter(part);
                if (parameter == null) return null; 
                parameters.Add(parameter);
            } 
            return parameters; 
        }
 
        MimeParameter ImportUrlParameter(MessagePart part) {
            //
            MimeParameter parameter = new MimeParameter();
            parameter.Name = CodeIdentifier.MakeValid(XmlConvert.DecodeName(part.Name)); 
            parameter.TypeName = IsRepeatingParameter(part) ? typeof(string[]).FullName : typeof(string).FullName;
            return parameter; 
        } 

        bool IsRepeatingParameter(MessagePart part) { 
            XmlSchemaComplexType type = (XmlSchemaComplexType)Schemas.Find(part.Type, typeof(XmlSchemaComplexType));
            if (type == null) return false;
            if (type.ContentModel == null) return false;
            if (type.ContentModel.Content == null) throw new ArgumentException(Res.GetString(Res.Missing2, type.Name, type.ContentModel.GetType().Name), "part"); 
            if (type.ContentModel.Content is XmlSchemaComplexContentExtension) {
                return ((XmlSchemaComplexContentExtension)type.ContentModel.Content).BaseTypeName == new XmlQualifiedName(Soap.ArrayType, Soap.Encoding); 
            } 
            else if (type.ContentModel.Content is XmlSchemaComplexContentRestriction) {
                return ((XmlSchemaComplexContentRestriction)type.ContentModel.Content).BaseTypeName == new XmlQualifiedName(Soap.ArrayType, Soap.Encoding); 
            }
            return false;
        }
 
        static void AppendMetadata(CodeAttributeDeclarationCollection from, CodeAttributeDeclarationCollection to) {
            foreach (CodeAttributeDeclaration attr in from) to.Add(attr); 
        } 

        CodeMemberMethod GenerateMethod(HttpMethodInfo method) { 
            MimeParameterCollection parameters = method.MimeParameters != null ? method.MimeParameters : method.UrlParameters;

            string[] parameterTypeNames = new string[parameters.Count];
            string[] parameterNames = new string[parameters.Count]; 

            for (int i = 0; i < parameters.Count; i++) { 
                MimeParameter param = parameters[i]; 
                parameterNames[i] = param.Name;
                parameterTypeNames[i] = param.TypeName; 
            }

            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
 
            CodeExpression[] formatterTypes = new CodeExpression[2];
 
            if (method.MimeReturn.ReaderType == null) { 
                formatterTypes[0] = new CodeTypeOfExpression(typeof(NopReturnReader).FullName);
            } 
            else {
                formatterTypes[0] = new CodeTypeOfExpression(method.MimeReturn.ReaderType.FullName);
            }
 
            if (method.MimeParameters != null)
                formatterTypes[1] = new CodeTypeOfExpression(method.MimeParameters.WriterType.FullName); 
            else 
                formatterTypes[1] = new CodeTypeOfExpression(typeof(UrlParameterWriter).FullName);
 
            WebCodeGenerator.AddCustomAttribute(metadata, typeof(HttpMethodAttribute), formatterTypes, new string[0], new CodeExpression[0]);


            CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, method.Name, new CodeFlags[parameterTypeNames.Length], parameterTypeNames, parameterNames, 
                                        method.MimeReturn.TypeName, metadata,
                                        CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract)); 
 
            AppendMetadata(method.MimeReturn.Attributes, mainCodeMethod.ReturnTypeCustomAttributes);
 
            mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));

            for (int i = 0; i < parameters.Count; i++) {
                AppendMetadata(parameters[i].Attributes, mainCodeMethod.Parameters[i].CustomAttributes); 
            }
 
            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[3]; 
                CreateInvokeParams(invokeParams, method, parameterNames);
                CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams); 
                if (method.MimeReturn.ReaderType != null) { 
                    mainCodeMethod.Statements.Add(new CodeMethodReturnStatement(new CodeCastExpression(method.MimeReturn.TypeName, invoke)));
                } 
                else {
                    mainCodeMethod.Statements.Add(new CodeExpressionStatement(invoke));
                }
 
                metadata = new CodeAttributeDeclarationCollection();
 
                string[] asyncParameterTypeNames = new string[parameterTypeNames.Length + 2]; 
                parameterTypeNames.CopyTo(asyncParameterTypeNames, 0);
                asyncParameterTypeNames[parameterTypeNames.Length] = typeof(AsyncCallback).FullName; 
                asyncParameterTypeNames[parameterTypeNames.Length + 1] = typeof(object).FullName;

                string[] asyncParameterNames = new string[parameterNames.Length + 2];
                parameterNames.CopyTo(asyncParameterNames, 0); 
                asyncParameterNames[parameterNames.Length] = "callback";
                asyncParameterNames[parameterNames.Length + 1] = "asyncState"; 
 
                if (oldAsync) {
                    CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + method.Name, new CodeFlags[asyncParameterTypeNames.Length], 
                        asyncParameterTypeNames, asyncParameterNames,
                        typeof(IAsyncResult).FullName, metadata, CodeFlags.IsPublic);
                    beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
 
                    invokeParams = new CodeExpression[5];
                    CreateInvokeParams(invokeParams, method, parameterNames); 
 
                    invokeParams[3] = new CodeArgumentReferenceExpression( "callback");
                    invokeParams[4] = new CodeArgumentReferenceExpression( "asyncState"); 

                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams);
                    beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
 
                    CodeMemberMethod endCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + method.Name, new CodeFlags[1],
                        new string[] { typeof(IAsyncResult).FullName }, 
                        new string[] { "asyncResult" }, 
                        method.MimeReturn.TypeName, metadata, CodeFlags.IsPublic);
                    endCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

                    CodeExpression expr = new CodeArgumentReferenceExpression( "asyncResult");
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { expr });
                    if (method.MimeReturn.ReaderType != null) { 
                        endCodeMethod.Statements.Add(new CodeMethodReturnStatement(new CodeCastExpression(method.MimeReturn.TypeName, invoke)));
                    } 
                    else { 
                        endCodeMethod.Statements.Add(new CodeExpressionStatement(invoke));
                    } 
                }
                if (newAsync) {
                    metadata = new CodeAttributeDeclarationCollection();
                    string uniqueMethodName = method.Name; 
                    string methodKey = MethodSignature(uniqueMethodName, method.MimeReturn.TypeName, new CodeFlags[parameterTypeNames.Length], parameterTypeNames);
                    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 userState = UniqueName("userState", parameterNames); 
                    CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName, 
                        parameterTypeNames, parameterNames, callbackMember, callbackName, userState);
 
                    // Generate InvokeAsync call
                    invokeParams = new CodeExpression[5];
                    CreateInvokeParams(invokeParams, method, parameterNames);
                    invokeParams[3] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember); 
                    invokeParams[4] = new CodeArgumentReferenceExpression(userState);
 
                    invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams); 
                    asyncCodeMethod.Statements.Add(invoke);
 
                    //  private void On_xxx_OperationCompleted(object arg) {..}
                    bool methodHasReturn = method.MimeReturn.ReaderType != null;
                    WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasReturn);
                    if (ExportContext[methodKey] == null) { 
                        // public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args);
                        WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasReturn ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName); 
 
                        if (methodHasReturn) {
                            ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, new string[] {method.MimeReturn.TypeName}, new string[] {"Result"}, 
                                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
                        }
                        ExportContext[methodKey] = delegateInfo;
                    } 
                }
            } 
            return mainCodeMethod; 
        }
 
        void CreateInvokeParams(CodeExpression[] invokeParams, HttpMethodInfo method, string[] parameterNames) {
            invokeParams[0] = new CodePrimitiveExpression(method.Name);

            CodeExpression left = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Url"); 
            CodeExpression right = new CodePrimitiveExpression(method.Href);
            invokeParams[1] = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.Add, right); 
 
            CodeExpression[] values = new CodeExpression[parameterNames.Length];
            for (int i = 0; i < parameterNames.Length; i++) { 
                values[i] = new CodeArgumentReferenceExpression( parameterNames[i]);
            }
            invokeParams[2] = new CodeArrayCreateExpression(typeof(object).FullName, values);
        } 

        protected override bool IsOperationFlowSupported(OperationFlow flow) { 
            return flow == OperationFlow.RequestResponse; 
        }
 
        //

        protected override CodeMemberMethod GenerateMethod() {
            HttpOperationBinding httpOperationBinding = (HttpOperationBinding)OperationBinding.Extensions.Find(typeof(HttpOperationBinding)); 
            if (httpOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingHttpOperationElement0));
 
            HttpMethodInfo method = new HttpMethodInfo(); 

            if (hasInputPayload) { 
                method.MimeParameters = ImportMimeParameters();
                if (method.MimeParameters == null) {
                    UnsupportedOperationWarning(Res.GetString(Res.NoInputMIMEFormatsWereRecognized0));
                    return null; 
                }
            } 
            else { 
                method.UrlParameters = ImportUrlParameters();
                if (method.UrlParameters == null) { 
                    UnsupportedOperationWarning(Res.GetString(Res.NoInputHTTPFormatsWereRecognized0));
                    return null;
                }
            } 
            method.MimeReturn = ImportMimeReturn();
            if (method.MimeReturn == null) { 
                UnsupportedOperationWarning(Res.GetString(Res.NoOutputMIMEFormatsWereRecognized0)); 
                return null;
            } 
            method.Name = MethodNames.AddUnique(MethodName, method);
            method.Href = httpOperationBinding.Location;
            return GenerateMethod(method);
        } 

        protected override CodeTypeDeclaration BeginClass() { 
            MethodNames.Clear(); 
            ExtraCodeClasses.Clear();
            CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection(); 
            if (Style == ServiceDescriptionImportStyle.Client) {
                WebCodeGenerator.AddCustomAttribute(metadata, typeof(DebuggerStepThroughAttribute), new CodeExpression[0]);
                WebCodeGenerator.AddCustomAttribute(metadata, typeof(DesignerCategoryAttribute), new CodeExpression[] { new CodePrimitiveExpression("code") });
            } 

            Type[] requiredTypes = new Type[] { 
                typeof(SoapDocumentMethodAttribute), 
                typeof(XmlAttributeAttribute),
                typeof(WebService), 
                typeof(Object),
                typeof(DebuggerStepThroughAttribute),
                typeof(DesignerCategoryAttribute),
                typeof(TransactionOption), 
            };
            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, BaseClass.FullName,
                new string[0], metadata, CodeFlags.IsPublic | flags, 
                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes));
 
            codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true)); 

            CodeConstructor ctor = WebCodeGenerator.AddConstructor(codeClass, new string[0], new string[0], null, CodeFlags.IsPublic); 
            ctor.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));

            HttpAddressBinding httpAddressBinding = Port == null ? null : (HttpAddressBinding)Port.Extensions.Find(typeof(HttpAddressBinding));
            string url =  (httpAddressBinding != null) ? httpAddressBinding.Location : null; 
            ServiceDescription serviceDescription = Binding.ServiceDescription;
            ProtocolImporterUtil.GenerateConstructorStatements(ctor, url, serviceDescription.AppSettingUrlKey, serviceDescription.AppSettingBaseUrl, false); 
 
            codeClasses.Add(codeClass);
            return codeClass; 
        }

        protected override void EndNamespace() {
            for (int i = 0; i < importers.Length; i++) { 
                importers[i].GenerateCode((MimeReturn[])importedReturns[i].ToArray(typeof(MimeReturn)),
                                          (MimeParameterCollection[])importedParameters[i].ToArray(typeof(MimeParameterCollection))); 
            } 

            foreach (CodeTypeDeclaration codeClass in codeClasses) { 
                if (codeClass.CustomAttributes == null)
                    codeClass.CustomAttributes = new CodeAttributeDeclarationCollection();

                for (int i = 0; i < importers.Length; i++) { 
                    importers[i].AddClassMetadata(codeClass);
                } 
            } 
            foreach(CodeTypeDeclaration declaration in ExtraCodeClasses) {
                this.CodeNamespace.Types.Add(declaration); 
            }
            CodeGenerator.ValidateIdentifiers(CodeNamespace);
        }
 
        internal abstract Type BaseClass { get; }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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