Example #1
0
        static void FillOperationsForInterface(ContractDescription cd, Type exactContractType, Type givenServiceType, bool isCallback)
        {
            // FIXME: load Behaviors
            MethodInfo [] contractMethods = /*exactContractType.IsInterface ? GetAllMethods (exactContractType) :*/ exactContractType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            MethodInfo [] serviceMethods  = contractMethods;
            if (givenServiceType != null && exactContractType.IsInterface)
            {
                var l = new List <MethodInfo> ();
                foreach (Type t in GetAllInterfaceTypes(exactContractType))
                {
                    l.AddRange(givenServiceType.GetInterfaceMap(t).TargetMethods);
                }
                serviceMethods = l.ToArray();
            }

            for (int i = 0; i < contractMethods.Length; ++i)
            {
                MethodInfo mi = contractMethods [i];
                OperationContractAttribute oca = GetOperationContractAttribute(mi);
                if (oca == null)
                {
                    continue;
                }
                MethodInfo end = null;
                if (oca.AsyncPattern)
                {
                    if (String.Compare("Begin", 0, mi.Name, 0, 5) != 0)
                    {
                        throw new InvalidOperationException("For async operation contract patterns, the initiator method name must start with 'Begin'.");
                    }
                    string endName = "End" + mi.Name.Substring(5);
                    end = mi.DeclaringType.GetMethod(endName);
                    if (end == null)
                    {
                        throw new InvalidOperationException(String.Format("'{0}' method is missing. For async operation contract patterns, corresponding End method is required for each Begin method.", endName));
                    }
                    if (GetOperationContractAttribute(end) != null)
                    {
                        throw new InvalidOperationException("Async 'End' method must not have OperationContractAttribute. It is automatically treated as the EndMethod of the corresponding 'Begin' method.");
                    }
                }
                OperationDescription od = GetOrCreateOperation(cd, mi, serviceMethods [i], oca, end != null ? end.ReturnType : null, isCallback);
                if (end != null)
                {
                    od.EndMethod = end;
                }
            }
        }
Example #2
0
        internal static OperationContractAttribute GetOperationContractAttribute(MethodInfo method)
        {
            OperationContractAttribute operationContractAttribute = GetSingleAttribute <OperationContractAttribute>(method);

            if (operationContractAttribute != null)
            {
                return(operationContractAttribute);
            }
            IOperationContractAttributeProvider operationContractProvider = GetFirstAttribute <IOperationContractAttributeProvider>(method);

            if (operationContractProvider != null)
            {
                return(operationContractProvider.GetOperationContractAttribute());
            }
            return(null);
        }
            private static string GetOperationAction(OperationContractAttribute operationContractAttribute, MethodInfo methodInfo)
            {
                if (!operationContractAttribute.Action.IsNullOrEmpty())
                {
                    return(operationContractAttribute.Action);
                }

                var sca = typeof(TContract).GetCustomAttributes(typeof(ServiceContractAttribute), false)
                          .Cast <ServiceContractAttribute>()
                          .Single();
                var serviceName   = sca.Name ?? typeof(TContract).Name;
                var operationName = operationContractAttribute.AsyncPattern ? methodInfo.Name.Substring("Begin".Length) : methodInfo.Name;

                // http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.action.aspx
                return(string.Format("{0}/{1}/{2}", sca.Namespace, serviceName, operationName));
            }
Example #4
0
            private static string GetOperationAction(OperationContractAttribute operationContractAttribute, MethodInfo methodInfo)
            {
                if (!operationContractAttribute.Action.IsNullOrEmpty())
                {
                    return(operationContractAttribute.Action);
                }

                var sca = typeof(TContract).GetCustomAttributes(typeof(ServiceContractAttribute), false)
                          .Cast <ServiceContractAttribute>()
                          .Single();
                var serviceName   = sca.Name ?? typeof(TContract).Name;
                var operationName = operationContractAttribute.AsyncPattern ? methodInfo.Name.Substring("Begin".Length) : methodInfo.Name;

                // https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.operationcontractattribute.action
                return($"{sca.Namespace}/{serviceName}/{operationName}");
            }
        internal static void VerifyOneway(Type interfaceType)
        {
            Debug.Assert(interfaceType.IsInterface);

            MethodInfo[] methods = interfaceType.GetMethods();
            foreach (MethodInfo method in methods)
            {
                object[] attributes = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
                Debug.Assert(attributes.Length == 1);

                OperationContractAttribute attribute = attributes[0] as OperationContractAttribute;
                if (attribute.IsOneWay == false)
                {
                    throw new InvalidOperationException("All operations on contract " + interfaceType + " must be one-way, but operation " + method.Name + " is not configured for one-way");
                }
            }
        }
        public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage methodCall = (IMethodCallMessage)msg;

            //得到操作名称
            object[] attributes = methodCall.MethodBase.GetCustomAttributes(typeof(OperationContractAttribute), true);
            OperationContractAttribute attribute = (OperationContractAttribute)attributes[0];
            string operationName = string.IsNullOrEmpty(attribute.Name) ? methodCall.MethodName : attribute.Name;

            //序列化请求消息
            Message requestMessage = this.MessageFormatters[operationName].SerializeRequest(this.MessageVersion, methodCall.InArgs);

            //添加必要的WS-Address报头
            EndpointAddress address = new EndpointAddress(this.Address);

            requestMessage.Headers.MessageId = new UniqueId(Guid.NewGuid());
            requestMessage.Headers.ReplyTo   = new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous");
            address.ApplyTo(requestMessage);

            //对请求消息进行编码,并将编码生成的字节发送通过HttpWebRequest向服务端发送
            HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(this.Address);

            webRequest.Method      = "Post";
            webRequest.KeepAlive   = true;
            webRequest.ContentType = "application/soap+xml; charset=utf-8";
            ArraySegment <byte> bytes = this.MessageEncoderFactory.Encoder.WriteMessage(requestMessage, int.MaxValue, BufferManager.CreateBufferManager(long.MaxValue, int.MaxValue));

            webRequest.ContentLength = bytes.Array.Length;
            webRequest.GetRequestStream().Write(bytes.Array, 0, bytes.Array.Length);
            webRequest.GetRequestStream().Close();
            WebResponse webResponse = webRequest.GetResponse();

            //对HttpResponse进行解码生成回复消息.
            Message responseMessage = this.MessageEncoderFactory.Encoder.ReadMessage(webResponse.GetResponseStream(), int.MaxValue);

            //回复消息进行反列化生成相应的对象,并映射为方法调用的返回值或者ref/out参数
            object[] allArgs = (object[])Array.CreateInstance(typeof(object), methodCall.ArgCount);
            Array.Copy(methodCall.Args, allArgs, methodCall.ArgCount);
            object[] refOutParameters = new object[GetRefOutParameterCount(methodCall.MethodBase)];
            object   returnValue      = this.MessageFormatters[operationName].DeserializeReply(responseMessage, refOutParameters);

            MapRefOutParameter(methodCall.MethodBase, allArgs, refOutParameters);

            //通过ReturnMessage的形式将返回值和ref/out参数返回
            return(new ReturnMessage(returnValue, allArgs, allArgs.Length, methodCall.LogicalCallContext, methodCall));
        }
Example #7
0
        /// <summary>
        /// This method wrapps an instance call
        /// </summary>
        /// <param name="methodInfo">The method to call</param>
        /// <param name="arrMethodArgs">The arguments to the method call</param>
        public object DoMethodCall(object[] arrMethodArgs, MethodInfo methodInfo)
        {
            ParameterInfo[] pis = methodInfo.GetParameters();
            if ((arrMethodArgs.Length != pis.Length))
            {
                throw new ArgumentException("Arguments count not match!");
            }
            var proxy = ServiceProxy.GetProxy(_serviceName);

            Parameter[] paras    = new Parameter[arrMethodArgs.Length];
            List <int>  outParas = new List <int>();

            for (int i = 0; i < pis.Length; i++)
            {
                var pi = pis[i];
                if (pi.IsOut || pi.ParameterType.IsByRef)
                {
                    paras[i] = new Parameter(arrMethodArgs[i], pi.ParameterType.GetElementType(), Com.Bj58.Spat.Gaea.Client.Proxy.Enum.ParaType.Out);
                    outParas.Add(i);
                }
                else
                {
                    paras[i] = new Parameter(arrMethodArgs[i], pi.ParameterType, Com.Bj58.Spat.Gaea.Client.Proxy.Enum.ParaType.In);
                }
            }
            string methodName = methodInfo.Name;
            var    atts       = methodInfo.GetCustomAttributes(typeof(Com.Bj58.Spat.Gaea.OperationContractAttribute), true);

            if (atts != null && atts.Length > 0)
            {
                OperationContractAttribute ma = (OperationContractAttribute)atts[0];
                if (!string.IsNullOrEmpty(ma.Name))
                {
                    methodName = ma.Name;
                }
                methodName = "$" + methodName;
            }
            var result = proxy.Invoke(methodInfo.ReturnType, _type, methodName, paras);

            for (int i = 0; i < outParas.Count && i < result.OutPara.Length; i++)
            {
                arrMethodArgs[outParas[i]] = result.OutPara[i];
            }
            return(result.Result);
        }
        static bool WebAttributesOCEExtender(MethodBase method, object[] customAttributes, ref OperationContractAttribute oca)
        {
            int caLength = customAttributes == null ? 0 : customAttributes.Length;

            if (method == null && caLength == 0)
            {
                return(false);
            }

            if (caLength == 0)
            {
                customAttributes = method.GetCustomAttributes(false);

                if (customAttributes.Length == 0)
                {
                    return(false);
                }
            }

            bool foundWebAttribute = false;

            foreach (object o in customAttributes)
            {
                if (o is WebInvokeAttribute || o is WebGetAttribute)
                {
                    foundWebAttribute = true;
                    break;
                }
            }

            if (!foundWebAttribute)
            {
                return(false);
            }

            // LAMESPEC: .NET allows for contract methods decorated only with
            // Web{Get,Invoke}Attribute and _without_ the OperationContractAttribute.
            if (oca == null)
            {
                oca = new OperationContractAttribute();
            }

            return(true);
        }
        static Uri GetOperationInfo(MethodInfo operation,
                                    Uri baseAddress,
                                    out string method,
                                    out WebInvokeAttribute webinvoke,
                                    out OperationContractAttribute operationcontract,
                                    out WebMessageFormat requestformat,
                                    out WebMessageFormat responseformat)
        {
            object[] customAttributes = operation.GetCustomAttributes(false);
            webinvoke         = customAttributes.Single(a => a is WebInvokeAttribute) as WebInvokeAttribute;
            method            = webinvoke.Method;
            operationcontract = customAttributes.Single(a => a is OperationContractAttribute) as OperationContractAttribute;
            requestformat     = webinvoke.RequestFormat;
            responseformat    = webinvoke.ResponseFormat;
            Uri relative = new Uri(webinvoke.UriTemplate, UriKind.Relative);
            Uri endpoint = new Uri(baseAddress, relative);

            return(endpoint);
        }
        public void TestReplyActionGeneration()
        {
            ProjectMappingManagerSetup.InitializeManager(ServiceProvider, "ProjectMapping.ServiceContractDsl.Tests.xml");

            ServiceContract      rootElement = CreateRoot(ServiceContractElementName, ServiceContractElementNamespace);
            Operation            op1         = new Operation(Store);
            WCFOperationContract oc          = new WCFOperationContract();

            oc.ReplyAction      = "foo";
            op1.ObjectExtender  = oc;
            op1.Name            = "op1";
            op1.ServiceContract = rootElement;
            string content = RunTemplate(rootElement);

            Type       generatedType             = CompileAndGetType(content);
            MethodInfo method                    = TypeAsserter.AssertMethod(op1.Name, generatedType);
            OperationContractAttribute operation = TypeAsserter.AssertAttribute <OperationContractAttribute>(method);

            Assert.AreEqual <string>(oc.ReplyAction, operation.ReplyAction);
        }
        public void TestProperUnwrappingOfSoapFaults()
        {
            ServiceDescription  serviceDescription  = new ServiceDescription(typeof(IServiceWithMessageContract));
            ContractDescription contractDescription = new ContractDescription(serviceDescription, typeof(IServiceWithMessageContract), new ServiceContractAttribute());

            System.Reflection.MethodInfo method = typeof(IServiceWithMessageContract).GetMethod(nameof(IServiceWithMessageContract.ThrowTypedFault));

            OperationContractAttribute contractAttribute = new OperationContractAttribute();

            ServiceModel.OperationDescription operationDescription = new ServiceModel.OperationDescription(contractDescription, method, contractAttribute);

            var faultInfo = Assert.Single(operationDescription.Faults);

            Assert.Equal("TypedSoapFault", faultInfo.Name);

            var properties    = faultInfo.GetProperties().Where(prop => prop.CustomAttributes.All(attr => attr.AttributeType.Name != "IgnoreDataMemberAttribute"));
            var faultProperty = Assert.Single(properties);

            Assert.Equal("MyIncludedProperty", faultProperty.Name);
        }
        public void UsesExistingOperationContractAttributeWithDecoratedMethod()
        {
            se.ObjectName = "UsesExistingOperationContractAttributeWithDecoratedMethod";
            se.TargetName = "decoratedService";
            se.AfterPropertiesSet();

            Type proxyType = se.GetObject() as Type;

            Assert.IsNotNull(proxyType);
            MethodInfo method = proxyType.GetMethod("SomeMethod");

            Assert.IsNotNull(method);

            object[] attrs = method.GetCustomAttributes(typeof(OperationContractAttribute), true);
            Assert.IsNotEmpty(attrs);
            Assert.AreEqual(1, attrs.Length);

            OperationContractAttribute oca = attrs[0] as OperationContractAttribute;

            Assert.AreEqual("MySomeMethod", oca.Name);
        }
Example #13
0
        public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
        {
            IMethodCallMessage methodCall = (IMethodCallMessage)msg;

            //得到操作名称
            object[] attributes = methodCall.MethodBase.GetCustomAttributes(typeof(OperationContractAttribute), false);
            OperationContractAttribute attribute = attributes[0] as OperationContractAttribute;
            string operationName = string.IsNullOrEmpty(attribute.Name) ? methodCall.MethodName : attribute.Name;

            Message requestMessage = MessageFormatter[operationName].SerializeRequest(this.MessageVersion, methodCall.InArgs);

            EndpointAddress address = new EndpointAddress(this.Address);

            requestMessage.Headers.MessageId = new UniqueId(Guid.NewGuid());
            requestMessage.Headers.ReplyTo   = new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous");
            address.ApplyTo(requestMessage);

            HttpWebRequest web = (HttpWebRequest)HttpWebRequest.Create(Address);

            web.Method      = "Post";
            web.KeepAlive   = true;
            web.ContentType = "application/soap+xml; charset=utf-8";


            ArraySegment <byte> bytes = this.MessageEncoderFactory.Encoder.WriteMessage(requestMessage, int.MaxValue, BufferManager.CreateBufferManager(long.MaxValue, int.MaxValue));

            web.ContentLength = bytes.Array.Length;
            web.GetRequestStream().Write(bytes.Array, 0, bytes.Array.Length);
            web.GetRequestStream().Close();
            WebResponse response = (WebResponse)web.GetResponse();

            //回复消息进行反列化生成相应的对象,并映射为方法调用的返回值或者ref/out参数
            object[] allArgs = (object[])Array.CreateInstance(typeof(object), methodCall.ArgCount);
            Array.Copy(methodCall.Args, allArgs, methodCall.ArgCount);
            Message responseMessage = this.MessageEncoderFactory.Encoder.ReadMessage(response.GetResponseStream(), int.MaxValue);
            object  result          = this.MessageFormatter[operationName].DeserializeReply(responseMessage, new object[GetRefOutParamterCount(methodCall.MethodBase)]);

            MapRefOutParameter(methodCall.MethodBase, allArgs, new object[GetRefOutParamterCount(methodCall.MethodBase)]);
            return(new ReturnMessage(result, allArgs, allArgs.Length, methodCall.LogicalCallContext, methodCall));
        }
Example #14
0
        public List <string> GetOperationsList()
        {
            List <string> operations = new List <string>();

            Type contractType = GetContractType();

            foreach (MethodInfo method in contractType.GetMethods())
            {
                object[] testAttributes = method.GetCustomAttributes(typeof(OperationContractAttribute), true);

                if (testAttributes.Length > 0)
                {
                    OperationContractAttribute attr = (OperationContractAttribute)testAttributes[0];
                    if (!string.IsNullOrEmpty(attr.Action))
                    {
                        operations.Add(method.Name);
                    }
                }
            }


            return(operations);
        }
        public void ShouldGetDefaultActionValue()
        {
            ProjectMappingManagerSetup.InitializeManager(ServiceProvider, "ProjectMapping.ServiceContractDsl.Tests.xml");
            ServiceContract rootElement = CreateRoot(ServiceContractElementName, ServiceContractElementNamespace);

            Operation op1 = new Operation(Store);

            op1.ServiceContract = rootElement;
            op1.ObjectExtender  = new WCFOperationContract();
            op1.Name            = "op1";

            // commit the tx and trigger the OperationAddRule so the action value will be filled with the default value
            this.transaction.Commit();
            this.transaction = null;

            string content = RunTemplate(rootElement);

            Type       generatedType             = CompileAndGetType(content);
            MethodInfo method                    = TypeAsserter.AssertMethod(op1.Name, generatedType);
            OperationContractAttribute operation = TypeAsserter.AssertAttribute <OperationContractAttribute>(method);

            Assert.AreEqual <string>(rootElement.Namespace + "/" + rootElement.Name + "/" + op1.Name, operation.Action);
        }
Example #16
0
        public OperationDescription(ContractDescription contract,
                                    MethodInfo operationMethod,
                                    MethodInfo implementingMethod,
                                    OperationContractAttribute contractAttribute)
        {
            Contract   = contract;
            Name       = contractAttribute.Name ?? operationMethod.Name;
            SoapAction = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}";
            IsOneWay   = contractAttribute.IsOneWay;
            IsMessageContractResponse =
                operationMethod
                .ReturnType
                .CustomAttributes
                .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null;
            ReplyAction        = contractAttribute.ReplyAction;
            DispatchMethod     = operationMethod;
            ImplementingMethod = implementingMethod;

            AllParameters = operationMethod.GetParameters()
                            .Select((info, index) => CreateParameterInfo(info, index, contract))
                            .ToArray();
            InParameters = AllParameters
                           .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef)
                           .ToArray();
            OutParameters = AllParameters
                            .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly)
                            .ToArray();

            IsMessageContractRequest =
                InParameters.Length == 1 &&
                InParameters.First().Parameter.ParameterType
                .CustomAttributes
                .FirstOrDefault(ca =>
                                ca.AttributeType == typeof(MessageContractAttribute)) != null;

            ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result";
        }
        private static OperationContractAttribute ConvertFromServiceModelOperationContractAttribute(object attr)
        {
            Fx.Assert(attr.GetType().FullName.Equals(ServiceReflector.SMOperationContractAttributeFullName), "Expected attribute of type S.SM.OperationContractAttribute");
            bool hasProtectionLevel = GetProperty <bool>(attr, "HasProtectionLevel");

            if (hasProtectionLevel)
            {
                // ProtectionLevel isn't supported yet so if it was set on the S.SM.SCA, then we can't do the mapping so throw
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new PlatformNotSupportedException("System.ServiceModel.OperationContractAttribute.ProtectionLevel"));
            }

            var    oca    = new OperationContractAttribute();
            string tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.Name));

            if (!string.IsNullOrEmpty(tmpStr))
            {
                oca.Name = tmpStr;
            }

            tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.Action));
            if (tmpStr != null) // String.Empty apparently is fine
            {
                oca.Action = tmpStr;
            }

            tmpStr = GetProperty <string>(attr, nameof(OperationContractAttribute.ReplyAction));
            if (tmpStr != null) // String.Empty apparently is fine
            {
                oca.ReplyAction = tmpStr;
            }

            oca.AsyncPattern = GetProperty <bool>(attr, nameof(OperationContractAttribute.AsyncPattern));
            oca.IsOneWay     = GetProperty <bool>(attr, nameof(OperationContractAttribute.IsOneWay));
            // TODO: IsInitiating and IsTerminating
            return(oca);
        }
        object ProcessMessage(AMFMessage amfMessage)
        {
            // Apply AMF-based operation selector

            /*
             * Dictionary<string, string> operationNameDictionary = new Dictionary<string, string>();
             * foreach (OperationDescription operation in _endpoint.Contract.Operations)
             * {
             *  try
             *  {
             *      operationNameDictionary.Add(operation.Name.ToLower(), operation.Name);
             *  }
             *  catch (ArgumentException)
             *  {
             *      throw new Exception(String.Format("The specified contract cannot be used with case insensitive URI dispatch because there is more than one operation named {0}", operation.Name));
             *  }
             * }
             */

            //SessionMode, CallbackContract, ProtectionLevel

            AMFMessage output = new AMFMessage(amfMessage.Version);

            for (int i = 0; i < amfMessage.BodyCount; i++)
            {
                AMFBody amfBody = amfMessage.GetBodyAt(i);
                object  content = amfBody.Content;
                if (content is IList)
                {
                    content = (content as IList)[0];
                }
                IMessage message = content as IMessage;
                if (message != null)
                {
                    //WCF should not assign client id for Flex...
                    if (message.clientId == null)
                    {
                        message.clientId = Guid.NewGuid().ToString("D");
                    }

                    //IMessage resultMessage = _endpoint.ServiceMessage(message);
                    IMessage       responseMessage = null;
                    CommandMessage commandMessage  = message as CommandMessage;
                    if (commandMessage != null && commandMessage.operation == CommandMessage.ClientPingOperation)
                    {
                        responseMessage      = new AcknowledgeMessage();
                        responseMessage.body = true;
                    }
                    else
                    {
                        RemotingMessage remotingMessage = message as RemotingMessage;
                        string          operation       = remotingMessage.operation;
                        //TODO: you could use an alias for a contract to expose a different name to the clients in the metadata using the Name property of the ServiceContract attribute
                        string source            = remotingMessage.source;
                        Type   serviceType       = TypeHelper.Locate(source);
                        Type   contractInterface = serviceType.GetInterface(_endpoint.Contract.ContractType.FullName);
                        //WCF also lets you apply the ServiceContract attribute directly on the service class. Avoid using it.
                        //ServiceContractAttribute serviceContractAttribute = ReflectionUtils.GetAttribute(typeof(ServiceContractAttribute), type, true) as ServiceContractAttribute;
                        if (contractInterface != null)
                        {
                            object     instance      = Activator.CreateInstance(serviceType);
                            IList      parameterList = remotingMessage.body as IList;
                            MethodInfo mi            = MethodHandler.GetMethod(contractInterface, operation, parameterList, false, false);
                            //MethodInfo mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false);
                            if (mi != null)
                            {
                                //TODO OperationContract attribute to alias it to a different publicly exposed name
                                OperationContractAttribute operationContractAttribute = ReflectionUtils.GetAttribute(typeof(OperationContractAttribute), mi, true) as OperationContractAttribute;
                                if (operationContractAttribute != null)
                                {
                                    //mi = MethodHandler.GetMethod(serviceType, operation, parameterList, false, false);
                                    ParameterInfo[] parameterInfos = mi.GetParameters();
                                    object[]        args           = new object[parameterInfos.Length];
                                    parameterList.CopyTo(args, 0);
                                    TypeHelper.NarrowValues(args, parameterInfos);
                                    object result = mi.Invoke(instance, args);
                                    if (!(result is IMessage))
                                    {
                                        responseMessage      = new AcknowledgeMessage();
                                        responseMessage.body = result;
                                    }
                                    else
                                    {
                                        responseMessage = result as IMessage;
                                    }
                                }
                                else
                                {
                                    responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract"));
                                }
                            }
                            else
                            {
                                responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException("Method in not part of an service contract"));
                            }
                        }
                        else
                        {
                            responseMessage = ErrorMessage.GetErrorMessage(remotingMessage, new SecurityException(String.Format("The specified contract {0} cannot be used with the source named {1} and operation named {2}", _endpoint.Contract.ContractType.Name, source, operation)));
                        }
                    }

                    if (responseMessage is AsyncMessage)
                    {
                        ((AsyncMessage)responseMessage).correlationId = message.messageId;
                    }
                    responseMessage.destination = message.destination;
                    responseMessage.clientId    = message.clientId;

                    ResponseBody responseBody = new ResponseBody(amfBody, responseMessage);
                    output.AddBody(responseBody);
                }
            }
            return(output);
        }
Example #19
0
        public static MessageDescription CreateMessageDescription(
            OperationContractAttribute oca, ParameterInfo[] plist, string name, string defaultNamespace, string action, bool isRequest, bool isCallback, Type retType, ICustomAttributeProvider retTypeAttributes)
        {
            var dir = isRequest ^ isCallback ? MessageDirection.Input : MessageDirection.Output;
            MessageDescription md = new MessageDescription(action, dir)
            {
                IsRequest = isRequest
            };

            MessageBodyDescription mb = md.Body;

            mb.WrapperName      = name + (isRequest ? String.Empty : "Response");
            mb.WrapperNamespace = defaultNamespace;

            if (oca.HasProtectionLevel)
            {
                md.ProtectionLevel = oca.ProtectionLevel;
            }

            // Parts
            int index = 0;

            foreach (ParameterInfo pi in plist)
            {
                // AsyncCallback and state are extraneous.
                if (oca.AsyncPattern && pi.Position == plist.Length - 2)
                {
                    break;
                }

                // They are ignored:
                // - out parameter in request
                // - neither out nor ref parameter in reply
                if (isRequest && pi.IsOut)
                {
                    continue;
                }
                if (!isRequest && !pi.IsOut && !pi.ParameterType.IsByRef)
                {
                    continue;
                }

                MessagePartDescription pd = CreatePartCore(GetMessageParameterAttribute(pi), pi.Name, defaultNamespace);
                pd.Index = index++;
                pd.Type  = MessageFilterOutByRef(pi.ParameterType);
                mb.Parts.Add(pd);
            }

            // ReturnValue
            if (!isRequest)
            {
                MessagePartDescription mp = CreatePartCore(GetMessageParameterAttribute(retTypeAttributes), name + "Result", mb.WrapperNamespace);
                mp.Index       = 0;
                mp.Type        = retType;
                mb.ReturnValue = mp;
            }

            // FIXME: fill properties.

            return(md);
        }
Example #20
0
        static internal XmlName GetOperationName(MethodInfo method)
        {
            OperationContractAttribute operationAttribute = GetOperationContractAttribute(method);

            return(NamingHelper.GetOperationName(GetLogicalName(method), operationAttribute.Name));
        }
 public OperationDescriptor(string action, string name, string ns, MethodInfo method, OperationContractAttribute contract, ServiceContractAttribute serviceContract)
 {
     Action          = action;
     Name            = name;
     Namespace       = ns;
     Method          = method;
     Contract        = contract;
     ServiceContract = serviceContract;
 }
Example #22
0
        private static void CheckInvalidMethodDeclaration(Type contractInterface, List <MethodComparator> methods)
        {
            foreach (MethodInfo m in contractInterface.GetMethods())
            {
                {
                    OperationContractAttribute ocAnnotation = TypeHelper.GetAttribute <OperationContractAttribute>(m);
                    if (ocAnnotation != null)
                    {
                        // 4. szabály ellenőrzése
                        if (!m.ReturnType.Equals(typeof(Stream)) && typeof(Stream).IsAssignableFrom(m.ReturnType))
                        {
                            throw new InvalidContractDefinitionException(String.Format("Return type '{0}' of the method '{1}' of contract '{2}' is not allowed. Use the base class instead.", m.ReturnType.FullName, m.Name, contractInterface.Name));
                        }
                        if (m.GetParameters().Length > 0)
                        {
                            foreach (ParameterInfo pt in m.GetParameters())
                            {
                                if (!pt.ParameterType.Equals(typeof(Stream)) && typeof(Stream).IsAssignableFrom(pt.ParameterType))
                                {
                                    throw new InvalidContractDefinitionException(String.Format("Parameter type '{0}' of the method '{1}' of contract '{2}' is not allowed. Use the base class instead.", pt.ParameterType.FullName, m.Name, contractInterface.Name));
                                }
                            }
                        }

                        // 5. szabály ellenőrzése
                        if (ocAnnotation.IsOneWay && !m.ReturnType.Equals(typeof(void)))
                        {
                            throw new InvalidContractDefinitionException(String.Format("Return type '{0}' of the method '{1}' of contract '{2}' is not allowed for OneWay mode.", m.ReturnType.FullName, m.Name, contractInterface.Name));
                        }
                        // 6. szabály ellenőrzése
                        if (!ocAnnotation.IsOneWay && !ocAnnotation.IsReliable)
                        {
                            throw new InvalidContractDefinitionException(String.Format("Invalid reliable mode setting for method '{0}' of the contract type '{1}'. Non reliable communication allowed only for OneWay mode.", m.Name, contractInterface.Name));
                        }
                    }
                    // 7. szabály ellenőrzése
                    MethodComparator cmp = new MethodComparator(m);
                    if (methods.Contains(cmp))
                    {
                        MethodComparator otherCmp = null;
                        foreach (MethodComparator mc in methods)
                        {
                            if (mc.Equals(cmp))
                            {
                                otherCmp = mc;
                                break;
                            }
                        }
                        OperationContractAttribute otherOcAnnotation = TypeHelper.GetAttribute <OperationContractAttribute>(otherCmp.Method);
                        if (ocAnnotation == null && otherOcAnnotation == null)
                        {
                            // do nothing
                        }
                        else if (ocAnnotation != null && otherOcAnnotation != null)
                        {
                            if (ocAnnotation.Direction != otherOcAnnotation.Direction)
                            {
                                throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'direction' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName));
                            }
                            if (ocAnnotation.IsOneWay != otherOcAnnotation.IsOneWay)
                            {
                                throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'isOneWay' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName));
                            }
                            if (ocAnnotation.IsReliable != otherOcAnnotation.IsReliable)
                            {
                                throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'isReliable' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName));
                            }
                            if (ocAnnotation.CallTimeout != otherOcAnnotation.CallTimeout)
                            {
                                throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Setting 'timeout' is different.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName));
                            }
                        }
                        else
                        {
                            // az egyiken van annotáció, a másikon meg nincs
                            throw new InvalidContractDefinitionException(String.Format("Different {0} definition found on method {1}. Contract interfaces are '{2}' and '{3}'. Same {4} must be exist on methods.", typeof(OperationContractAttribute).Name, m.Name, contractInterface.Name, otherCmp.Method.DeclaringType.FullName, typeof(OperationContractAttribute).Name));
                        }
                    }
                    else
                    {
                        methods.Add(cmp);
                    }
                }
            }
        }
Example #23
0
        public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute)
        {
            Contract       = contract;
            Name           = contractAttribute.Name ?? GetNameByAction(contractAttribute.Action) ?? operationMethod.Name;
            SoapAction     = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}";
            IsOneWay       = contractAttribute.IsOneWay;
            ReplyAction    = contractAttribute.ReplyAction;
            DispatchMethod = operationMethod;

            var returnType = operationMethod.ReturnType;

            if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task <>))
            {
                returnType = returnType.GenericTypeArguments[0];
            }

            IsMessageContractResponse = returnType.CustomAttributes
                                        .FirstOrDefault(ca => ca.AttributeType == typeof(MessageContractAttribute)) != null;

            AllParameters = operationMethod.GetParameters()
                            .Select((info, index) => CreateParameterInfo(info, index, contract))
                            .ToArray();
            InParameters = AllParameters
                           .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef)
                           .ToArray();
            OutParameters = AllParameters
                            .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly)
                            .ToArray();

            IsMessageContractRequest =
                InParameters.Length == 1 &&
                InParameters.First().Parameter.ParameterType
                .CustomAttributes
                .FirstOrDefault(ca =>
                                ca.AttributeType == typeof(MessageContractAttribute)) != null;

            ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result";

            var faultContractAttributes = operationMethod.GetCustomAttributes <FaultContractAttribute>();

            Faults = faultContractAttributes
                     .Where(a => a.DetailType?.Name != null)
                     .Select(a => a.DetailType)
                     .ToArray();
        }
        static OperationDescription GetOrCreateOperation(
            ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod,
            OperationContractAttribute oca,
            Type asyncReturnType)
        {
            string name = oca.Name ?? (oca.AsyncPattern ? mi.Name.Substring(5) : mi.Name);

            OperationDescription od = null;

            foreach (OperationDescription iter in cd.Operations)
            {
                if (iter.Name == name)
                {
                    od = iter;
                    break;
                }
            }
            if (od == null)
            {
                od          = new OperationDescription(name, cd);
                od.IsOneWay = oca.IsOneWay;
                if (oca.HasProtectionLevel)
                {
                    od.ProtectionLevel = oca.ProtectionLevel;
                }
                od.Messages.Add(GetMessage(od, mi, oca, true, null));
                if (!od.IsOneWay)
                {
                    od.Messages.Add(GetMessage(od, mi, oca, false, asyncReturnType));
                }
                foreach (ServiceKnownTypeAttribute a in cd.ContractType.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false))
                {
                    foreach (Type t in a.GetTypes())
                    {
                        od.KnownTypes.Add(t);
                    }
                }
                foreach (ServiceKnownTypeAttribute a in serviceMethod.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false))
                {
                    foreach (Type t in a.GetTypes())
                    {
                        od.KnownTypes.Add(t);
                    }
                }
                cd.Operations.Add(od);
            }
            else if (oca.AsyncPattern && od.BeginMethod != null ||
                     !oca.AsyncPattern && od.SyncMethod != null)
            {
                throw new InvalidOperationException("A contract cannot have two operations that have the identical names and different set of parameters.");
            }

            if (oca.AsyncPattern)
            {
                od.BeginMethod = mi;
            }
            else
            {
                od.SyncMethod = mi;
            }
            od.IsInitiating  = oca.IsInitiating;
            od.IsTerminating = oca.IsTerminating;

            if (mi != serviceMethod)
            {
                foreach (object obj in mi.GetCustomAttributes(typeof(IOperationBehavior), true))
                {
                    od.Behaviors.Add((IOperationBehavior)obj);
                }
            }

            if (serviceMethod != null)
            {
                foreach (object obj in serviceMethod.GetCustomAttributes(typeof(IOperationBehavior), true))
                {
                    od.Behaviors.Add((IOperationBehavior)obj);
                }
            }
#if !NET_2_1
            if (od.Behaviors.Find <OperationBehaviorAttribute>() == null)
            {
                od.Behaviors.Add(new OperationBehaviorAttribute());
            }
#endif
            // FIXME: fill KnownTypes, Behaviors and Faults.

            return(od);
        }
 public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute)
 {
     Contract       = contract;
     Name           = contractAttribute.Name ?? operationMethod.Name;
     SoapAction     = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{Name}";
     IsOneWay       = contractAttribute.IsOneWay;
     ReplyAction    = contractAttribute.ReplyAction;
     DispatchMethod = operationMethod;
 }
        static ContractDescription GetContract(Type givenContractType, Type givenServiceType, bool assumeServiceContract)
        {
            // FIXME: serviceType should be used for specifying attributes like OperationBehavior.

            Type exactContractType       = null;
            ServiceContractAttribute sca = null;
            Dictionary <Type, ServiceContractAttribute> contracts =
                GetServiceContractAttributes(givenServiceType ?? givenContractType);

            if (contracts.ContainsKey(givenContractType))
            {
                exactContractType = givenContractType;
                sca = contracts[givenContractType];
            }
            else
            {
                foreach (Type t in contracts.Keys)
                {
                    if (t.IsAssignableFrom(givenContractType))
                    {
                        if (t.IsAssignableFrom(exactContractType))                          // exact = IDerived, t = IBase
                        {
                            continue;
                        }
                        if (sca != null && (exactContractType == null || !exactContractType.IsAssignableFrom(t)))                          // t = IDerived, exact = IBase
                        {
                            throw new InvalidOperationException("The contract type of " + givenContractType + " is ambiguous: can be either " + exactContractType + " or " + t);
                        }
                        exactContractType = t;
                        sca = contracts [t];
                    }
                }
            }
            if (exactContractType == null)
            {
                exactContractType = givenContractType;
            }
            if (sca == null)
            {
                if (assumeServiceContract)
                {
                    sca = new ServiceContractAttribute();
                }
                else
                {
                    throw new InvalidOperationException(String.Format("Attempted to get contract type from '{0}' which neither is a service contract nor does it inherit service contract.", givenContractType));
                }
            }
            string name = sca.Name ?? exactContractType.Name;
            string ns   = sca.Namespace ?? "http://tempuri.org/";

            ContractDescription cd =
                new ContractDescription(name, ns);

            cd.ContractType         = exactContractType;
            cd.CallbackContractType = sca.CallbackContract;
            cd.SessionMode          = sca.SessionMode;
            if (sca.ConfigurationName != null)
            {
                cd.ConfigurationName = sca.ConfigurationName;
            }
            else
            {
                cd.ConfigurationName = exactContractType.FullName;
            }
            if (sca.HasProtectionLevel)
            {
                cd.ProtectionLevel = sca.ProtectionLevel;
            }

            // FIXME: load Behaviors
            MethodInfo [] contractMethods = exactContractType.IsInterface ? GetAllMethods(exactContractType) : exactContractType.GetMethods();
            MethodInfo [] serviceMethods  = contractMethods;
            if (givenServiceType != null && exactContractType.IsInterface)
            {
                var l = new List <MethodInfo> ();
                foreach (Type t in GetAllInterfaceTypes(exactContractType))
                {
                    l.AddRange(givenServiceType.GetInterfaceMap(t).TargetMethods);
                }
                serviceMethods = l.ToArray();
            }

            for (int i = 0; i < contractMethods.Length; ++i)
            {
                MethodInfo mi = contractMethods [i];
                OperationContractAttribute oca = GetOperationContractAttribute(mi);
                if (oca == null)
                {
                    continue;
                }
                MethodInfo end = null;
                if (oca.AsyncPattern)
                {
                    if (String.Compare("Begin", 0, mi.Name, 0, 5) != 0)
                    {
                        throw new InvalidOperationException("For async operation contract patterns, the initiator method name must start with 'Begin'.");
                    }
                    string endName = "End" + mi.Name.Substring(5);
                    end = mi.DeclaringType.GetMethod(endName);
                    if (end == null)
                    {
                        throw new InvalidOperationException(String.Format("'{0}' method is missing. For async operation contract patterns, corresponding End method is required for each Begin method.", endName));
                    }
                    if (GetOperationContractAttribute(end) != null)
                    {
                        throw new InvalidOperationException("Async 'End' method must not have OperationContractAttribute. It is automatically treated as the EndMethod of the corresponding 'Begin' method.");
                    }
                }
                OperationDescription od = GetOrCreateOperation(cd,
                                                               mi,
                                                               serviceMethods [i],
                                                               oca,
                                                               end != null ? end.ReturnType : null);
                if (end != null)
                {
                    od.EndMethod = end;
                }
            }

            // FIXME: enable this when I found where this check is needed.

            /*
             * if (cd.Operations.Count == 0)
             *      throw new InvalidOperationException (String.Format ("The service contract type {0} has no operation. At least one operation must exist.", contractType));
             */
            return(cd);
        }
Example #27
0
 public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute)
 {
     Contract         = contract;
     Name             = contractAttribute.Name ?? operationMethod.Name;
     SoapAction       = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}";
     IsOneWay         = contractAttribute.IsOneWay;
     ReplyAction      = contractAttribute.ReplyAction;
     DispatchMethod   = operationMethod;
     NormalParameters = operationMethod.GetParameters().Where(x => !x.IsOut && !x.ParameterType.IsByRef)
                        .Select(info => CreateParameterInfo(info, contract)).ToArray();
     OutParameters = operationMethod.GetParameters().Where(x => x.IsOut || x.ParameterType.IsByRef)
                     .Select(info => CreateParameterInfo(info, contract)).ToArray();
     ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result";
 }
Example #28
0
        static MessageDescription GetMessage(
            OperationDescription od, MethodInfo mi,
            OperationContractAttribute oca, bool isRequest,
            bool isCallback, Type asyncReturnType)
        {
            ContractDescription cd = od.DeclaringContract;

            ParameterInfo []         plist       = mi.GetParameters();
            Type                     messageType = null;
            string                   action      = isRequest ? oca.Action : oca.ReplyAction;
            MessageContractAttribute mca;

            Type retType = asyncReturnType;

            if (!isRequest && retType == null)
            {
                retType = mi.ReturnType;
            }

            // If the argument is only one and has [MessageContract]
            // then infer it as a typed messsage
            if (isRequest)
            {
                int len = mi.Name.StartsWith("Begin", StringComparison.Ordinal) ? 3 : 1;
                mca = plist.Length != len ? null :
                      GetMessageContractAttribute(plist [0].ParameterType);
                if (mca != null)
                {
                    messageType = plist [0].ParameterType;
                }
            }
            else
            {
                mca = GetMessageContractAttribute(retType);
                if (mca != null)
                {
                    messageType = retType;
                }
            }

            if (action == null)
            {
                action = String.Concat(cd.Namespace,
                                       cd.Namespace.Length == 0 ? "urn:" : cd.Namespace.EndsWith("/") ? "" : "/", cd.Name, "/",
                                       od.Name, isRequest ? String.Empty : "Response");
            }

            MessageDescription md;

            if (mca != null)
            {
                md = CreateMessageDescription(messageType, cd.Namespace, action, isRequest, isCallback, mca);
            }
            else
            {
                md = CreateMessageDescription(oca, plist, od.Name, cd.Namespace, action, isRequest, isCallback, retType);
            }

            // ReturnValue
            if (!isRequest)
            {
                MessagePartDescription mp = CreatePartCore(GetMessageParameterAttribute(mi.ReturnTypeCustomAttributes), od.Name + "Result", md.Body.WrapperNamespace);
                mp.Index            = 0;
                mp.Type             = mca != null ? typeof(void) : retType;
                md.Body.ReturnValue = mp;
            }

            return(md);
        }
Example #29
0
        static OperationDescription GetOrCreateOperation(
            ContractDescription cd, MethodInfo mi, MethodInfo serviceMethod,
            OperationContractAttribute oca,
            Type asyncReturnType,
            bool isCallback,
            Type givenServiceType)
        {
            string name = oca.Name ?? (oca.AsyncPattern ? mi.Name.Substring(5) : mi.Name);

            OperationDescription od = cd.Operations.FirstOrDefault(o => o.Name == name && o.InCallbackContract == isCallback);

            if (od == null)
            {
                od          = new OperationDescription(name, cd);
                od.IsOneWay = oca.IsOneWay;
                if (oca.HasProtectionLevel)
                {
                    od.ProtectionLevel = oca.ProtectionLevel;
                }

                if (HasInvalidMessageContract(mi, oca.AsyncPattern))
                {
                    throw new InvalidOperationException(String.Format("The operation {0} contains more than one parameters and one or more of them are marked with MessageContractAttribute, but the attribute must be used within an operation that has only one parameter.", od.Name));
                }

#if !MOONLIGHT
                var xfa = serviceMethod.GetCustomAttribute <XmlSerializerFormatAttribute> (false);
                if (xfa != null)
                {
                    od.Behaviors.Add(new XmlSerializerOperationBehavior(od, xfa));
                }
#endif
                var dfa = serviceMethod.GetCustomAttribute <DataContractFormatAttribute> (false);
                if (dfa != null)
                {
                    od.Behaviors.Add(new DataContractSerializerOperationBehavior(od, dfa));
                }

                od.Messages.Add(GetMessage(od, mi, oca, true, isCallback, null));
                if (!od.IsOneWay)
                {
                    var md = GetMessage(od, mi, oca, false, isCallback, asyncReturnType);
                    od.Messages.Add(md);
                    var mpa = mi.ReturnParameter.GetCustomAttribute <MessageParameterAttribute> (true);
                    if (mpa != null)
                    {
                        var mpd = md.Body.Parts.FirstOrDefault(pd => pd.Name == mpa.Name);
                        if (mpd != null)
                        {
                            md.Body.Parts.Remove(mpd);
                            md.Body.ReturnValue = mpd;
                            mpd.Name            = mpa.Name;
                        }
                        else if (md.Body.ReturnValue == null)
                        {
                            throw new InvalidOperationException(String.Format("Specified message part '{0}' in MessageParameterAttribute on the return value, was not found", mpa.Name));
                        }
                    }
                }
                var knownTypeAtts =
                    cd.ContractType.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false).Union(
                        mi.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false)).Union(
                        serviceMethod.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), false));
                foreach (ServiceKnownTypeAttribute a in knownTypeAtts)
                {
                    foreach (Type t in a.GetTypes(givenServiceType))
                    {
                        od.KnownTypes.Add(t);
                    }
                }
                foreach (FaultContractAttribute a in mi.GetCustomAttributes(typeof(FaultContractAttribute), false))
                {
                    var fname = a.Name ?? a.DetailType.Name + "Fault";
                    var fns   = a.Namespace ?? cd.Namespace;
                    var fd    = new FaultDescription(a.Action ?? cd.Namespace + cd.Name + "/" + od.Name + fname)
                    {
                        DetailType = a.DetailType, Name = fname, Namespace = fns
                    };
#if !NET_2_1
                    if (a.HasProtectionLevel)
                    {
                        fd.ProtectionLevel = a.ProtectionLevel;
                    }
#endif
                    od.Faults.Add(fd);
                }
                cd.Operations.Add(od);
            }
            else if ((oca.AsyncPattern && od.BeginMethod != null && od.BeginMethod != mi ||
                      !oca.AsyncPattern && od.SyncMethod != null && od.SyncMethod != mi) && od.InCallbackContract == isCallback)
            {
                throw new InvalidOperationException(String.Format("contract '{1}' cannot have two operations for '{0}' that have the identical names and different set of parameters.", name, cd.Name));
            }

            if (oca.AsyncPattern)
            {
                od.BeginMethod = mi;
            }
            else
            {
                od.SyncMethod = mi;
            }
            od.IsInitiating  = oca.IsInitiating;
            od.IsTerminating = oca.IsTerminating;

            if (mi != serviceMethod)
            {
                foreach (object obj in mi.GetCustomAttributes(typeof(IOperationBehavior), true))
                {
                    od.Behaviors.Add((IOperationBehavior)obj);
                }
            }

            if (serviceMethod != null)
            {
                foreach (object obj in serviceMethod.GetCustomAttributes(typeof(IOperationBehavior), true))
                {
                    od.Behaviors.Add((IOperationBehavior)obj);
                }
            }
#if !NET_2_1
            if (od.Behaviors.Find <OperationBehaviorAttribute>() == null)
            {
                od.Behaviors.Add(new OperationBehaviorAttribute());
            }
#endif
            // FIXME: fill KnownTypes, Behaviors and Faults.

            if (isCallback)
            {
                od.InCallbackContract = true;
            }
            else
            {
                od.InOrdinalContract = true;
            }

            return(od);
        }
 public OperationDescription(ContractDescription contract, MethodInfo operationMethod, OperationContractAttribute contractAttribute)
 {
     Contract       = contract;
     Name           = contractAttribute.Name ?? operationMethod.Name;
     SoapAction     = contractAttribute.Action ?? $"{contract.Namespace.TrimEnd('/')}/{contract.Name}/{Name}";
     IsOneWay       = contractAttribute.IsOneWay;
     ReplyAction    = contractAttribute.ReplyAction;
     DispatchMethod = operationMethod;
     AllParameters  = operationMethod.GetParameters()
                      .Select((info, index) => CreateParameterInfo(info, index, contract))
                      .ToArray();
     InParameters = AllParameters
                    .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.OutOnlyRef)
                    .ToArray();
     OutParameters = AllParameters
                     .Where(soapParam => soapParam.Direction != SoapMethodParameterDirection.InOnly)
                     .ToArray();
     ReturnName = operationMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? Name + "Result";
 }