Example #1
0
        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 GenerateClassForBinding()
        {
            try {
                if (bindingCount == 1 && service != null && Style != ServiceDescriptionImportStyle.ServerInterface)
                {
                    // If there is only one binding, then use the name of the service
                    className = XmlConvert.DecodeName(service.Name);
                }
                else
                {
                    // If multiple bindings, then use the name of the binding
                    className = binding.Name;
                    if (Style == ServiceDescriptionImportStyle.ServerInterface)
                    {
                        // append "I" if we are generating interfaces
                        className = "I" + CodeIdentifier.MakePascal(className);
                    }
                }
                className      = XmlConvert.DecodeName(className);
                className      = ClassNames.AddUnique(CodeIdentifier.MakeValid(className), null);
                this.codeClass = BeginClass();
                int methodCount = 0;
                for (int i = 0; i < portType.Operations.Count; i++)
                {
                    MoveToOperation(portType.Operations[i]);

                    if (!IsOperationFlowSupported(operation.Messages.Flow))
                    {
                        //
                        switch (operation.Messages.Flow)
                        {
                        case OperationFlow.SolicitResponse:
                            UnsupportedOperationWarning(Res.GetString(Res.SolicitResponseIsNotSupported0));
                            continue;

                        case OperationFlow.RequestResponse:
                            UnsupportedOperationWarning(Res.GetString(Res.RequestResponseIsNotSupported0));
                            continue;

                        case OperationFlow.OneWay:
                            UnsupportedOperationWarning(Res.GetString(Res.OneWayIsNotSupported0));
                            continue;

                        case OperationFlow.Notification:
                            UnsupportedOperationWarning(Res.GetString(Res.NotificationIsNotSupported0));
                            continue;
                        }
                    }

                    CodeMemberMethod method;
                    try {
                        method = GenerateMethod();
                    }
                    catch (Exception e) {
                        if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                        {
                            throw;
                        }
                        throw new InvalidOperationException(Res.GetString(Res.UnableToImportOperation1, operation.Name), e);
                    }

                    if (method != null)
                    {
                        AddExtensionWarningComments(codeClass.Comments, operationBinding.Extensions);
                        if (operationBinding.Input != null)
                        {
                            AddExtensionWarningComments(codeClass.Comments, operationBinding.Input.Extensions);
                        }
                        if (operationBinding.Output != null)
                        {
                            AddExtensionWarningComments(codeClass.Comments, operationBinding.Output.Extensions);
                        }
                        methodCount++;
                    }
                }
                bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
                                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) &&
                                ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates);
                if (newAsync && methodCount > 0 && Style == ServiceDescriptionImportStyle.Client)
                {
                    CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
                    string           cancelAsync       = "CancelAsync";
                    string           cancelMethodName  = MethodNames.AddUnique(cancelAsync, cancelAsync);
                    CodeMemberMethod asyncCancelMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, cancelMethodName,
                                                                                    new CodeFlags[1], new string[] { typeof(object).FullName }, new string[] { "userState" },
                                                                                    typeof(void).FullName,
                                                                                    metadata,
                                                                                    CodeFlags.IsPublic | (cancelAsync != cancelMethodName ? 0 : CodeFlags.IsNew));

                    asyncCancelMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
                    CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), cancelAsync);
                    invoke.Parameters.Add(new CodeArgumentReferenceExpression("userState"));
                    asyncCancelMethod.Statements.Add(invoke);
                }

                EndClass();

                if (portType.Operations.Count == 0)
                {
                    NoMethodsGeneratedWarning();
                }

                AddExtensionWarningComments(codeClass.Comments, binding.Extensions);
                if (port != null)
                {
                    AddExtensionWarningComments(codeClass.Comments, port.Extensions);
                }

                codeNamespace.Types.Add(codeClass);
            }
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                {
                    throw;
                }
                throw new InvalidOperationException(Res.GetString(Res.UnableToImportBindingFromNamespace2, binding.Name, binding.ServiceDescription.TargetNamespace), e);
            }
        }