internal static SoapReflectedMethod ReflectMethod(LogicalMethodInfo methodInfo, bool client, XmlReflectionImporter xmlImporter, SoapReflectionImporter soapImporter, string defaultNs) { try { SoapReflectedMethod soapMethod = new SoapReflectedMethod(); MethodAttribute methodAttribute = new MethodAttribute(); object serviceAttr = GetSoapServiceAttribute(methodInfo.DeclaringType); bool serviceDefaultIsEncoded = ServiceDefaultIsEncoded(serviceAttr); object methodAttr = GetSoapMethodAttribute(methodInfo); if (methodAttr == null) { if (client) { return(null); // method attribute required on the client } if (serviceAttr is SoapRpcServiceAttribute) { methodAttr = new SoapRpcMethodAttribute(); } else { methodAttr = new SoapDocumentMethodAttribute(); } } if (methodAttr is SoapRpcMethodAttribute) { SoapRpcMethodAttribute attr = (SoapRpcMethodAttribute)methodAttr; soapMethod.rpc = true; soapMethod.use = SoapBindingUse.Encoded; soapMethod.oneWay = attr.OneWay; methodAttribute.action = attr.Action; methodAttribute.binding = attr.Binding; methodAttribute.requestName = attr.RequestElementName; methodAttribute.requestNs = attr.RequestNamespace; methodAttribute.responseName = attr.ResponseElementName; methodAttribute.responseNs = attr.ResponseNamespace; } else { SoapDocumentMethodAttribute attr = (SoapDocumentMethodAttribute)methodAttr; soapMethod.rpc = false; soapMethod.use = attr.Use; soapMethod.paramStyle = attr.ParameterStyle; soapMethod.oneWay = attr.OneWay; methodAttribute.action = attr.Action; methodAttribute.binding = attr.Binding; methodAttribute.requestName = attr.RequestElementName; methodAttribute.requestNs = attr.RequestNamespace; methodAttribute.responseName = attr.ResponseElementName; methodAttribute.responseNs = attr.ResponseNamespace; if (soapMethod.use == SoapBindingUse.Default) { if (serviceAttr is SoapDocumentServiceAttribute) { soapMethod.use = ((SoapDocumentServiceAttribute)serviceAttr).Use; } if (soapMethod.use == SoapBindingUse.Default) { soapMethod.use = SoapBindingUse.Literal; } } if (soapMethod.paramStyle == SoapParameterStyle.Default) { if (serviceAttr is SoapDocumentServiceAttribute) { soapMethod.paramStyle = ((SoapDocumentServiceAttribute)serviceAttr).ParameterStyle; } if (soapMethod.paramStyle == SoapParameterStyle.Default) { soapMethod.paramStyle = SoapParameterStyle.Wrapped; } } } if (methodAttribute.binding.Length > 0) { if (client) { throw new InvalidOperationException(Res.GetString(Res.WebInvalidBindingPlacement, methodAttr.GetType().Name)); } soapMethod.binding = WebServiceBindingReflector.GetAttribute(methodInfo, methodAttribute.binding); } WebMethodAttribute webMethodAttribute = WebMethodReflector.GetAttribute(methodInfo); soapMethod.name = webMethodAttribute.MessageName; if (soapMethod.name.Length == 0) { soapMethod.name = methodInfo.Name; } string requestElementName; if (soapMethod.rpc) { requestElementName = methodInfo.Name; } else { requestElementName = methodAttribute.requestName.Length == 0 ? soapMethod.name : methodAttribute.requestName; } string requestNamespace = methodAttribute.requestNs; if (requestNamespace == null) { if (soapMethod.binding != null && soapMethod.binding.Namespace != null && soapMethod.binding.Namespace.Length != 0) { requestNamespace = soapMethod.binding.Namespace; } else { requestNamespace = defaultNs; } } string responseElementName = methodAttribute.responseName.Length == 0 ? soapMethod.name + "Response": methodAttribute.responseName; string responseNamespace = methodAttribute.responseNs; if (responseNamespace == null) { if (soapMethod.binding != null && soapMethod.binding.Namespace != null && soapMethod.binding.Namespace.Length != 0) { responseNamespace = soapMethod.binding.Namespace; } else { responseNamespace = defaultNs; } } SoapParameterInfo[] inParameters = ReflectParameters(methodInfo.InParameters, requestNamespace); SoapParameterInfo[] outParameters = ReflectParameters(methodInfo.OutParameters, responseNamespace); soapMethod.action = methodAttribute.action; if (soapMethod.action == null) { soapMethod.action = GetDefaultAction(defaultNs, methodInfo); } soapMethod.methodInfo = methodInfo; if (soapMethod.oneWay) { if (outParameters.Length > 0) { throw new ArgumentException(Res.GetString(Res.WebOneWayOutParameters), "methodInfo"); } if (methodInfo.ReturnType != typeof(void)) { throw new ArgumentException(Res.GetString(Res.WebOneWayReturnValue), "methodInfo"); } } XmlReflectionMember[] members = new XmlReflectionMember[inParameters.Length]; for (int i = 0; i < members.Length; i++) { SoapParameterInfo soapParamInfo = inParameters[i]; XmlReflectionMember member = new XmlReflectionMember(); member.MemberName = soapParamInfo.parameterInfo.Name; member.MemberType = soapParamInfo.parameterInfo.ParameterType; if (member.MemberType.IsByRef) { member.MemberType = member.MemberType.GetElementType(); } member.XmlAttributes = soapParamInfo.xmlAttributes; member.SoapAttributes = soapParamInfo.soapAttributes; members[i] = member; } soapMethod.requestMappings = ImportMembersMapping(xmlImporter, soapImporter, serviceDefaultIsEncoded, soapMethod.rpc, soapMethod.use, soapMethod.paramStyle, requestElementName, requestNamespace, methodAttribute.requestNs == null, members, true); if (GetSoapServiceRoutingStyle(serviceAttr) == SoapServiceRoutingStyle.RequestElement && soapMethod.paramStyle == SoapParameterStyle.Bare && soapMethod.requestMappings.Count != 1) { throw new ArgumentException(Res.GetString(Res.WhenUsingAMessageStyleOfParametersAsDocument0), "methodInfo"); } string elementName = ""; string elementNamespace = ""; if (soapMethod.paramStyle == SoapParameterStyle.Bare) { if (soapMethod.requestMappings.Count == 1) { elementName = soapMethod.requestMappings[0].ElementName; elementNamespace = soapMethod.requestMappings[0].Namespace; } // else: can't route on request element -- we match on an empty qname, // normal rules apply for duplicates } else { elementName = soapMethod.requestMappings.ElementName; elementNamespace = soapMethod.requestMappings.Namespace; } soapMethod.requestElementName = new XmlQualifiedName(elementName, elementNamespace); if (!soapMethod.oneWay) { int numOutParams = outParameters.Length; int count = 0; CodeIdentifiers identifiers = null; if (methodInfo.ReturnType != typeof(void)) { numOutParams++; count = 1; identifiers = new CodeIdentifiers(); } members = new XmlReflectionMember[numOutParams]; for (int i = 0; i < outParameters.Length; i++) { SoapParameterInfo soapParamInfo = outParameters[i]; XmlReflectionMember member = new XmlReflectionMember(); member.MemberName = soapParamInfo.parameterInfo.Name; member.MemberType = soapParamInfo.parameterInfo.ParameterType; if (member.MemberType.IsByRef) { member.MemberType = member.MemberType.GetElementType(); } member.XmlAttributes = soapParamInfo.xmlAttributes; member.SoapAttributes = soapParamInfo.soapAttributes; members[count++] = member; if (identifiers != null) { identifiers.Add(member.MemberName, null); } } if (methodInfo.ReturnType != typeof(void)) { XmlReflectionMember member = new XmlReflectionMember(); member.MemberName = identifiers.MakeUnique(soapMethod.name + "Result"); member.MemberType = methodInfo.ReturnType; member.IsReturnValue = true; member.XmlAttributes = new XmlAttributes(methodInfo.ReturnTypeCustomAttributeProvider); member.XmlAttributes.XmlRoot = null; // Ignore XmlRoot attribute used by get/post member.SoapAttributes = new SoapAttributes(methodInfo.ReturnTypeCustomAttributeProvider); members[0] = member; } soapMethod.responseMappings = ImportMembersMapping(xmlImporter, soapImporter, serviceDefaultIsEncoded, soapMethod.rpc, soapMethod.use, soapMethod.paramStyle, responseElementName, responseNamespace, methodAttribute.responseNs == null, members, false); } SoapExtensionAttribute[] extensionAttributes = (SoapExtensionAttribute[])methodInfo.GetCustomAttributes(typeof(SoapExtensionAttribute)); soapMethod.extensions = new SoapReflectedExtension[extensionAttributes.Length]; for (int i = 0; i < extensionAttributes.Length; i++) { soapMethod.extensions[i] = new SoapReflectedExtension(extensionAttributes[i].ExtensionType, extensionAttributes[i]); } Array.Sort(soapMethod.extensions); SoapHeaderAttribute[] headerAttributes = (SoapHeaderAttribute[])methodInfo.GetCustomAttributes(typeof(SoapHeaderAttribute)); Array.Sort(headerAttributes, new SoapHeaderAttributeComparer()); Hashtable headerTypes = new Hashtable(); soapMethod.headers = new SoapReflectedHeader[headerAttributes.Length]; int front = 0; int back = soapMethod.headers.Length; ArrayList inHeaders = new ArrayList(); ArrayList outHeaders = new ArrayList(); for (int i = 0; i < soapMethod.headers.Length; i++) { SoapHeaderAttribute headerAttribute = headerAttributes[i]; SoapReflectedHeader soapHeader = new SoapReflectedHeader(); Type declaringType = methodInfo.DeclaringType; if ((soapHeader.memberInfo = declaringType.GetField(headerAttribute.MemberName)) != null) { soapHeader.headerType = ((FieldInfo)soapHeader.memberInfo).FieldType; } else if ((soapHeader.memberInfo = declaringType.GetProperty(headerAttribute.MemberName)) != null) { soapHeader.headerType = ((PropertyInfo)soapHeader.memberInfo).PropertyType; } else { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderMissing); } if (soapHeader.headerType.IsArray) { soapHeader.headerType = soapHeader.headerType.GetElementType(); soapHeader.repeats = true; if (soapHeader.headerType != typeof(SoapUnknownHeader) && soapHeader.headerType != typeof(SoapHeader)) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderType); } } if (MemberHelper.IsStatic(soapHeader.memberInfo)) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderStatic); } if (!MemberHelper.CanRead(soapHeader.memberInfo)) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderRead); } if (!MemberHelper.CanWrite(soapHeader.memberInfo)) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderWrite); } if (!typeof(SoapHeader).IsAssignableFrom(soapHeader.headerType)) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderType); } SoapHeaderDirection direction = headerAttribute.Direction; if (soapMethod.oneWay && (direction & (SoapHeaderDirection.Out | SoapHeaderDirection.Fault)) != 0) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebHeaderOneWayOut); } if (headerTypes.Contains(soapHeader.headerType)) { SoapHeaderDirection prevDirection = (SoapHeaderDirection)headerTypes[soapHeader.headerType]; if ((prevDirection & direction) != 0) { throw HeaderException(headerAttribute.MemberName, methodInfo.DeclaringType, Res.WebMultiplyDeclaredHeaderTypes); } headerTypes[soapHeader.headerType] = direction | prevDirection; } else { headerTypes[soapHeader.headerType] = direction; } if (soapHeader.headerType != typeof(SoapHeader) && soapHeader.headerType != typeof(SoapUnknownHeader)) { XmlReflectionMember member = new XmlReflectionMember(); member.MemberName = soapHeader.headerType.Name; member.MemberType = soapHeader.headerType; member.OverrideIsNullable = true; if ((direction & SoapHeaderDirection.In) != 0) { inHeaders.Add(member); } if ((direction & (SoapHeaderDirection.Out | SoapHeaderDirection.Fault)) != 0) { outHeaders.Add(member); } soapHeader.custom = true; } soapHeader.direction = direction; // Put generic header mappings at the end of the list so they are found last during header processing if (!soapHeader.custom) { soapMethod.headers[--back] = soapHeader; } else { soapMethod.headers[front++] = soapHeader; } } soapMethod.inHeaderMappings = ImportMembersMapping(xmlImporter, soapImporter, serviceDefaultIsEncoded, false, soapMethod.use, SoapParameterStyle.Bare, "InHeaders", defaultNs, true, (XmlReflectionMember[])inHeaders.ToArray(typeof(XmlReflectionMember)), false); if (!soapMethod.oneWay) { soapMethod.outHeaderMappings = ImportMembersMapping(xmlImporter, soapImporter, serviceDefaultIsEncoded, false, soapMethod.use, SoapParameterStyle.Bare, "OutHeaders", defaultNs, true, (XmlReflectionMember[])outHeaders.ToArray(typeof(XmlReflectionMember)), false); } return(soapMethod); } catch (Exception e) { throw new InvalidOperationException(Res.GetString(Res.WebReflectionErrorMethod, methodInfo.DeclaringType.Name, methodInfo.Name), e); } }