| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Description
- {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Reflection;
- using System.Runtime;
- using System.Security;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Dispatcher;
- using System.Xml;
- using System.Xml.Serialization;
- public class XmlSerializerOperationBehavior : IOperationBehavior, IWsdlExportExtension
- {
- readonly Reflector.OperationReflector reflector;
- readonly bool builtInOperationBehavior;
- public XmlSerializerOperationBehavior(OperationDescription operation)
- : this(operation, null)
- {
- }
- public XmlSerializerOperationBehavior(OperationDescription operation, XmlSerializerFormatAttribute attribute)
- {
- if (operation == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operation");
- #pragma warning suppress 56506 // Declaring contract cannot be null
- Reflector parentReflector = new Reflector(operation.DeclaringContract.Namespace, operation.DeclaringContract.ContractType);
- #pragma warning suppress 56506 // parentReflector cannot be null
- this.reflector = parentReflector.ReflectOperation(operation, attribute ?? new XmlSerializerFormatAttribute());
- }
- internal XmlSerializerOperationBehavior(OperationDescription operation, XmlSerializerFormatAttribute attribute, Reflector parentReflector)
- : this(operation, attribute)
- {
- // used by System.ServiceModel.Web
- this.reflector = parentReflector.ReflectOperation(operation, attribute ?? new XmlSerializerFormatAttribute());
- }
- XmlSerializerOperationBehavior(Reflector.OperationReflector reflector, bool builtInOperationBehavior)
- {
- Fx.Assert(reflector != null, "");
- this.reflector = reflector;
- this.builtInOperationBehavior = builtInOperationBehavior;
- }
- internal Reflector.OperationReflector OperationReflector
- {
- get { return this.reflector; }
- }
- internal bool IsBuiltInOperationBehavior
- {
- get { return this.builtInOperationBehavior; }
- }
- public XmlSerializerFormatAttribute XmlSerializerFormatAttribute
- {
- get
- {
- return this.reflector.Attribute;
- }
- }
- internal static XmlSerializerOperationFormatter CreateOperationFormatter(OperationDescription operation)
- {
- return new XmlSerializerOperationBehavior(operation).CreateFormatter();
- }
- internal static XmlSerializerOperationFormatter CreateOperationFormatter(OperationDescription operation, XmlSerializerFormatAttribute attr)
- {
- return new XmlSerializerOperationBehavior(operation, attr).CreateFormatter();
- }
- internal static void AddBehaviors(ContractDescription contract)
- {
- AddBehaviors(contract, false);
- }
- internal static void AddBuiltInBehaviors(ContractDescription contract)
- {
- AddBehaviors(contract, true);
- }
- static void AddBehaviors(ContractDescription contract, bool builtInOperationBehavior)
- {
- Reflector reflector = new Reflector(contract.Namespace, contract.ContractType);
- foreach (OperationDescription operation in contract.Operations)
- {
- Reflector.OperationReflector operationReflector = reflector.ReflectOperation(operation);
- if (operationReflector != null)
- {
- bool isInherited = operation.DeclaringContract != contract;
- if (!isInherited)
- {
- operation.Behaviors.Add(new XmlSerializerOperationBehavior(operationReflector, builtInOperationBehavior));
- operation.Behaviors.Add(new XmlSerializerOperationGenerator(new XmlSerializerImportOptions()));
- }
- }
- }
- }
- internal XmlSerializerOperationFormatter CreateFormatter()
- {
- return new XmlSerializerOperationFormatter(reflector.Operation, reflector.Attribute, reflector.Request, reflector.Reply);
- }
- XmlSerializerFaultFormatter CreateFaultFormatter(SynchronizedCollection<FaultContractInfo> faultContractInfos)
- {
- return new XmlSerializerFaultFormatter(faultContractInfos, reflector.XmlSerializerFaultContractInfos);
- }
- void IOperationBehavior.Validate(OperationDescription description)
- {
- }
- void IOperationBehavior.AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
- {
- }
- void IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
- {
- if (description == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
- if (dispatch == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dispatch");
- if (dispatch.Formatter == null)
- {
- dispatch.Formatter = (IDispatchMessageFormatter)CreateFormatter();
- dispatch.DeserializeRequest = reflector.RequestRequiresSerialization;
- dispatch.SerializeReply = reflector.ReplyRequiresSerialization;
- }
- if (reflector.Attribute.SupportFaults)
- {
- if (!dispatch.IsFaultFormatterSetExplicit)
- {
- dispatch.FaultFormatter = (IDispatchFaultFormatter)CreateFaultFormatter(dispatch.FaultContractInfos);
- }
- else
- {
- var wrapper = dispatch.FaultFormatter as IDispatchFaultFormatterWrapper;
- if (wrapper != null)
- {
- wrapper.InnerFaultFormatter = (IDispatchFaultFormatter)CreateFaultFormatter(dispatch.FaultContractInfos);
- }
- }
- }
- }
- void IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
- {
- if (description == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
- if (proxy == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("proxy");
- if (proxy.Formatter == null)
- {
- proxy.Formatter = (IClientMessageFormatter)CreateFormatter();
- proxy.SerializeRequest = reflector.RequestRequiresSerialization;
- proxy.DeserializeReply = reflector.ReplyRequiresSerialization;
- }
- if (reflector.Attribute.SupportFaults && !proxy.IsFaultFormatterSetExplicit)
- proxy.FaultFormatter = (IClientFaultFormatter)CreateFaultFormatter(proxy.FaultContractInfos);
- }
- void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext endpointContext)
- {
- if (exporter == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exporter");
- if (endpointContext == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointContext");
- MessageContractExporter.ExportMessageBinding(exporter, endpointContext, typeof(XmlSerializerMessageContractExporter), this.reflector.Operation);
- }
- void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext)
- {
- if (exporter == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exporter");
- if (contractContext == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractContext");
- new XmlSerializerMessageContractExporter(exporter, contractContext, this.reflector.Operation, this).ExportMessageContract();
- }
- public Collection<XmlMapping> GetXmlMappings()
- {
- Collection<XmlMapping> mappings = new Collection<XmlMapping>();
- if (OperationReflector.Request != null && OperationReflector.Request.HeadersMapping != null)
- mappings.Add(OperationReflector.Request.HeadersMapping);
- if (OperationReflector.Request != null && OperationReflector.Request.BodyMapping != null)
- mappings.Add(OperationReflector.Request.BodyMapping);
- if (OperationReflector.Reply != null && OperationReflector.Reply.HeadersMapping != null)
- mappings.Add(OperationReflector.Reply.HeadersMapping);
- if (OperationReflector.Reply != null && OperationReflector.Reply.BodyMapping != null)
- mappings.Add(OperationReflector.Reply.BodyMapping);
- return mappings;
- }
- // helper for reflecting operations
- internal class Reflector
- {
- readonly XmlSerializerImporter importer;
- readonly SerializerGenerationContext generation;
- Collection<OperationReflector> operationReflectors = new Collection<OperationReflector>();
- object thisLock = new object();
- internal Reflector(string defaultNs, Type type)
- {
- this.importer = new XmlSerializerImporter(defaultNs);
- this.generation = new SerializerGenerationContext(type);
- }
- internal void EnsureMessageInfos()
- {
- lock (this.thisLock)
- {
- foreach (OperationReflector operationReflector in operationReflectors)
- {
- operationReflector.EnsureMessageInfos();
- }
- }
- }
- static XmlSerializerFormatAttribute FindAttribute(OperationDescription operation)
- {
- Type contractType = operation.DeclaringContract != null ? operation.DeclaringContract.ContractType : null;
- XmlSerializerFormatAttribute contractFormatAttribute = contractType != null ? TypeLoader.GetFormattingAttribute(contractType, null) as XmlSerializerFormatAttribute : null;
- return TypeLoader.GetFormattingAttribute(operation.OperationMethod, contractFormatAttribute) as XmlSerializerFormatAttribute;
- }
- // auto-reflects the operation, returning null if no attribute was found or inherited
- internal OperationReflector ReflectOperation(OperationDescription operation)
- {
- XmlSerializerFormatAttribute attr = FindAttribute(operation);
- if (attr == null)
- return null;
- return ReflectOperation(operation, attr);
- }
- // overrides the auto-reflection with an attribute
- internal OperationReflector ReflectOperation(OperationDescription operation, XmlSerializerFormatAttribute attrOverride)
- {
- OperationReflector operationReflector = new OperationReflector(this, operation, attrOverride, true/*reflectOnDemand*/);
- operationReflectors.Add(operationReflector);
- return operationReflector;
- }
- internal class OperationReflector
- {
- readonly Reflector parent;
- internal readonly OperationDescription Operation;
- internal readonly XmlSerializerFormatAttribute Attribute;
- internal readonly bool IsEncoded;
- internal readonly bool IsRpc;
- internal readonly bool IsOneWay;
- internal readonly bool RequestRequiresSerialization;
- internal readonly bool ReplyRequiresSerialization;
- readonly string keyBase;
- MessageInfo request;
- MessageInfo reply;
- SynchronizedCollection<XmlSerializerFaultContractInfo> xmlSerializerFaultContractInfos;
- internal OperationReflector(Reflector parent, OperationDescription operation, XmlSerializerFormatAttribute attr, bool reflectOnDemand)
- {
- Fx.Assert(parent != null, "");
- Fx.Assert(operation != null, "");
- Fx.Assert(attr != null, "");
- OperationFormatter.Validate(operation, attr.Style == OperationFormatStyle.Rpc, attr.IsEncoded);
- this.parent = parent;
- this.Operation = operation;
- this.Attribute = attr;
- this.IsEncoded = attr.IsEncoded;
- this.IsRpc = (attr.Style == OperationFormatStyle.Rpc);
- this.IsOneWay = operation.Messages.Count == 1;
- this.RequestRequiresSerialization = !operation.Messages[0].IsUntypedMessage;
- this.ReplyRequiresSerialization = !this.IsOneWay && !operation.Messages[1].IsUntypedMessage;
- MethodInfo methodInfo = operation.OperationMethod;
- if (methodInfo == null)
- {
- // keyBase needs to be unique within the scope of the parent reflector
- keyBase = string.Empty;
- if (operation.DeclaringContract != null)
- {
- keyBase = operation.DeclaringContract.Name + "," + operation.DeclaringContract.Namespace + ":";
- }
- keyBase = keyBase + operation.Name;
- }
- else
- keyBase = methodInfo.DeclaringType.FullName + ":" + methodInfo.ToString();
- foreach (MessageDescription message in operation.Messages)
- foreach (MessageHeaderDescription header in message.Headers)
- SetUnknownHeaderInDescription(header);
- if (!reflectOnDemand)
- {
- this.EnsureMessageInfos();
- }
- }
- private void SetUnknownHeaderInDescription(MessageHeaderDescription header)
- {
- if (this.IsEncoded) //XmlAnyElementAttribute does not apply
- return;
- if (header.AdditionalAttributesProvider != null)
- {
- XmlAttributes xmlAttributes = new XmlAttributes(header.AdditionalAttributesProvider);
- foreach (XmlAnyElementAttribute anyElement in xmlAttributes.XmlAnyElements)
- {
- if (String.IsNullOrEmpty(anyElement.Name))
- {
- header.IsUnknownHeaderCollection = true;
- }
- }
- }
- }
- string ContractName
- {
- get { return this.Operation.DeclaringContract.Name; }
- }
- string ContractNamespace
- {
- get { return this.Operation.DeclaringContract.Namespace; }
- }
- internal MessageInfo Request
- {
- get
- {
- parent.EnsureMessageInfos();
- return this.request;
- }
- }
- internal MessageInfo Reply
- {
- get
- {
- parent.EnsureMessageInfos();
- return this.reply;
- }
- }
- internal SynchronizedCollection<XmlSerializerFaultContractInfo> XmlSerializerFaultContractInfos
- {
- get
- {
- parent.EnsureMessageInfos();
- return this.xmlSerializerFaultContractInfos;
- }
- }
- internal void EnsureMessageInfos()
- {
- if (this.request == null)
- {
- foreach (Type knownType in Operation.KnownTypes)
- {
- if (knownType == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxKnownTypeNull, Operation.Name)));
- parent.importer.IncludeType(knownType, IsEncoded);
- }
- this.request = CreateMessageInfo(this.Operation.Messages[0], ":Request");
- if (this.request != null && this.IsRpc && this.Operation.IsValidateRpcWrapperName && this.request.BodyMapping.XsdElementName != this.Operation.Name)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageBodyPartNameInvalid, Operation.Name, this.Operation.Messages[0].MessageName, request.BodyMapping.XsdElementName, this.Operation.Name)));
- if (!this.IsOneWay)
- {
- this.reply = CreateMessageInfo(this.Operation.Messages[1], ":Response");
- XmlName responseName = TypeLoader.GetBodyWrapperResponseName(this.Operation.Name);
- if (this.reply != null && this.IsRpc && this.Operation.IsValidateRpcWrapperName && this.reply.BodyMapping.XsdElementName != responseName.EncodedName)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageBodyPartNameInvalid, Operation.Name, this.Operation.Messages[1].MessageName, reply.BodyMapping.XsdElementName, responseName.EncodedName)));
- }
- if (this.Attribute.SupportFaults)
- {
- GenerateXmlSerializerFaultContractInfos();
- }
- }
- }
- void GenerateXmlSerializerFaultContractInfos()
- {
- SynchronizedCollection<XmlSerializerFaultContractInfo> faultInfos = new SynchronizedCollection<XmlSerializerFaultContractInfo>();
- for (int i = 0; i < this.Operation.Faults.Count; i++)
- {
- FaultDescription fault = this.Operation.Faults[i];
- FaultContractInfo faultContractInfo = new FaultContractInfo(fault.Action, fault.DetailType, fault.ElementName, fault.Namespace, this.Operation.KnownTypes);
- XmlQualifiedName elementName;
- XmlMembersMapping xmlMembersMapping = this.ImportFaultElement(fault, out elementName);
- SerializerStub serializerStub = parent.generation.AddSerializer(xmlMembersMapping);
- faultInfos.Add(new XmlSerializerFaultContractInfo(faultContractInfo, serializerStub, elementName));
- }
- this.xmlSerializerFaultContractInfos = faultInfos;
- }
- MessageInfo CreateMessageInfo(MessageDescription message, string key)
- {
- if (message.IsUntypedMessage)
- return null;
- MessageInfo info = new MessageInfo();
- if (message.IsTypedMessage)
- key = message.MessageType.FullName + ":" + IsEncoded + ":" + IsRpc;
- XmlMembersMapping headersMapping = LoadHeadersMapping(message, key + ":Headers");
- info.SetHeaders(parent.generation.AddSerializer(headersMapping));
- MessagePartDescriptionCollection rpcEncodedTypedMessgeBodyParts;
- info.SetBody(parent.generation.AddSerializer(LoadBodyMapping(message, key, out rpcEncodedTypedMessgeBodyParts)), rpcEncodedTypedMessgeBodyParts);
- CreateHeaderDescriptionTable(message, info, headersMapping);
- return info;
- }
- private void CreateHeaderDescriptionTable(MessageDescription message, MessageInfo info, XmlMembersMapping headersMapping)
- {
- int headerNameIndex = 0;
- OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable = new OperationFormatter.MessageHeaderDescriptionTable();
- info.SetHeaderDescriptionTable(headerDescriptionTable);
- foreach (MessageHeaderDescription header in message.Headers)
- {
- if (header.IsUnknownHeaderCollection)
- info.SetUnknownHeaderDescription(header);
- else if (headersMapping != null)
- {
- XmlMemberMapping memberMapping = headersMapping[headerNameIndex++];
- string headerName, headerNs;
- if (IsEncoded)
- {
- headerName = memberMapping.TypeName;
- headerNs = memberMapping.TypeNamespace;
- }
- else
- {
- headerName = memberMapping.XsdElementName;
- headerNs = memberMapping.Namespace;
- }
- if (headerName != header.Name)
- {
- if (message.MessageType != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNameMismatchInMessageContract, message.MessageType, header.MemberInfo.Name, header.Name, headerName)));
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNameMismatchInOperation, this.Operation.Name, this.Operation.DeclaringContract.Name, this.Operation.DeclaringContract.Namespace, header.Name, headerName)));
- }
- if (headerNs != header.Namespace)
- {
- if (message.MessageType != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNamespaceMismatchInMessageContract, message.MessageType, header.MemberInfo.Name, header.Namespace, headerNs)));
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeaderNamespaceMismatchInOperation, this.Operation.Name, this.Operation.DeclaringContract.Name, this.Operation.DeclaringContract.Namespace, header.Namespace, headerNs)));
- }
- headerDescriptionTable.Add(headerName, headerNs, header);
- }
- }
- }
- XmlMembersMapping LoadBodyMapping(MessageDescription message, string mappingKey, out MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts)
- {
- MessagePartDescription returnPart;
- string wrapperName, wrapperNs;
- MessagePartDescriptionCollection bodyParts;
- if (IsEncoded && message.IsTypedMessage && message.Body.WrapperName == null)
- {
- MessagePartDescription wrapperPart = GetWrapperPart(message);
- returnPart = null;
- rpcEncodedTypedMessageBodyParts = bodyParts = GetWrappedParts(wrapperPart);
- wrapperName = wrapperPart.Name;
- wrapperNs = wrapperPart.Namespace;
- }
- else
- {
- rpcEncodedTypedMessageBodyParts = null;
- returnPart = OperationFormatter.IsValidReturnValue(message.Body.ReturnValue) ? message.Body.ReturnValue : null;
- bodyParts = message.Body.Parts;
- wrapperName = message.Body.WrapperName;
- wrapperNs = message.Body.WrapperNamespace;
- }
- bool isWrapped = (wrapperName != null);
- bool hasReturnValue = returnPart != null;
- int paramCount = bodyParts.Count + (hasReturnValue ? 1 : 0);
- if (paramCount == 0 && !isWrapped) // no need to create serializer
- {
- return null;
- }
- XmlReflectionMember[] members = new XmlReflectionMember[paramCount];
- int paramIndex = 0;
- if (hasReturnValue)
- members[paramIndex++] = XmlSerializerHelper.GetXmlReflectionMember(returnPart, IsRpc, IsEncoded, isWrapped);
- for (int i = 0; i < bodyParts.Count; i++)
- members[paramIndex++] = XmlSerializerHelper.GetXmlReflectionMember(bodyParts[i], IsRpc, IsEncoded, isWrapped);
- if (!isWrapped)
- wrapperNs = ContractNamespace;
- return ImportMembersMapping(wrapperName, wrapperNs, members, isWrapped, IsRpc, mappingKey);
- }
- private MessagePartDescription GetWrapperPart(MessageDescription message)
- {
- if (message.Body.Parts.Count != 1)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxRpcMessageMustHaveASingleBody, Operation.Name, message.MessageName)));
- MessagePartDescription bodyPart = message.Body.Parts[0];
- Type bodyObjectType = bodyPart.Type;
- if (bodyObjectType.BaseType != null && bodyObjectType.BaseType != typeof(object))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInherited, bodyObjectType.FullName)));
- if (typeof(IEnumerable).IsAssignableFrom(bodyObjectType))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInterface, bodyObjectType.FullName, typeof(IEnumerable).FullName)));
- if (typeof(IXmlSerializable).IsAssignableFrom(bodyObjectType))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxBodyObjectTypeCannotBeInterface, bodyObjectType.FullName, typeof(IXmlSerializable).FullName)));
- return bodyPart;
- }
- private MessagePartDescriptionCollection GetWrappedParts(MessagePartDescription bodyPart)
- {
- Type bodyObjectType = bodyPart.Type;
- MessagePartDescriptionCollection partList = new MessagePartDescriptionCollection();
- foreach (MemberInfo member in bodyObjectType.GetMembers(BindingFlags.Instance | BindingFlags.Public))
- {
- if ((member.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0)
- continue;
- if (member.IsDefined(typeof(SoapIgnoreAttribute), false/*inherit*/))
- continue;
- XmlName xmlName = new XmlName(member.Name);
- MessagePartDescription part = new MessagePartDescription(xmlName.EncodedName, string.Empty);
- part.AdditionalAttributesProvider = part.MemberInfo = member;
- part.Index = part.SerializationPosition = partList.Count;
- part.Type = (member.MemberType == MemberTypes.Property) ? ((PropertyInfo)member).PropertyType : ((FieldInfo)member).FieldType;
- if (bodyPart.HasProtectionLevel)
- part.ProtectionLevel = bodyPart.ProtectionLevel;
- partList.Add(part);
- }
- return partList;
- }
- XmlMembersMapping LoadHeadersMapping(MessageDescription message, string mappingKey)
- {
- int headerCount = message.Headers.Count;
- if (headerCount == 0)
- return null;
- if (IsEncoded)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxHeadersAreNotSupportedInEncoded, message.MessageName)));
- int unknownHeaderCount = 0, headerIndex = 0;
- XmlReflectionMember[] members = new XmlReflectionMember[headerCount];
- for (int i = 0; i < headerCount; i++)
- {
- MessageHeaderDescription header = message.Headers[i];
- if (!header.IsUnknownHeaderCollection)
- {
- members[headerIndex++] = XmlSerializerHelper.GetXmlReflectionMember(header, false/*isRpc*/, IsEncoded, false/*isWrapped*/);
- }
- else
- {
- unknownHeaderCount++;
- }
- }
- if (unknownHeaderCount == headerCount)
- {
- return null;
- }
- if (unknownHeaderCount > 0)
- {
- XmlReflectionMember[] newMembers = new XmlReflectionMember[headerCount - unknownHeaderCount];
- Array.Copy(members, newMembers, newMembers.Length);
- members = newMembers;
- }
- return ImportMembersMapping(ContractName, ContractNamespace, members, false /*isWrapped*/, false /*isRpc*/, mappingKey);
- }
- internal XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, string mappingKey)
- {
- string key = mappingKey.StartsWith(":", StringComparison.Ordinal) ? keyBase + mappingKey : mappingKey;
- return this.parent.importer.ImportMembersMapping(new XmlName(elementName, true /*isEncoded*/), ns, members, hasWrapperElement, rpc, this.IsEncoded, key);
- }
- internal XmlMembersMapping ImportFaultElement(FaultDescription fault, out XmlQualifiedName elementName)
- {
- // the number of reflection members is always 1 because there is only one fault detail type
- XmlReflectionMember[] members = new XmlReflectionMember[1];
- XmlName faultElementName = fault.ElementName;
- string faultNamespace = fault.Namespace;
- if (faultElementName == null)
- {
- XmlTypeMapping mapping = this.parent.importer.ImportTypeMapping(fault.DetailType, this.IsEncoded);
- faultElementName = new XmlName(mapping.ElementName, this.IsEncoded);
- faultNamespace = mapping.Namespace;
- if (faultElementName == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxFaultTypeAnonymous, this.Operation.Name, fault.DetailType.FullName)));
- }
- elementName = new XmlQualifiedName(faultElementName.DecodedName, faultNamespace);
- members[0] = XmlSerializerHelper.GetXmlReflectionMember(null /*memberName*/, faultElementName, faultNamespace, fault.DetailType,
- null /*additionalAttributesProvider*/, false /*isMultiple*/, this.IsEncoded, false /*isWrapped*/);
- string mappingKey = "fault:" + faultElementName.DecodedName + ":" + faultNamespace;
- return ImportMembersMapping(faultElementName.EncodedName, faultNamespace, members, false /*hasWrapperElement*/, this.IsRpc, mappingKey);
- }
- }
- class XmlSerializerImporter
- {
- readonly string defaultNs;
- XmlReflectionImporter xmlImporter;
- SoapReflectionImporter soapImporter;
- Dictionary<string, XmlMembersMapping> xmlMappings;
- internal XmlSerializerImporter(string defaultNs)
- {
- this.defaultNs = defaultNs;
- this.xmlImporter = null;
- this.soapImporter = null;
- }
- SoapReflectionImporter SoapImporter
- {
- get
- {
- if (this.soapImporter == null)
- {
- this.soapImporter = new SoapReflectionImporter(NamingHelper.CombineUriStrings(defaultNs, "encoded"));
- }
- return this.soapImporter;
- }
- }
- XmlReflectionImporter XmlImporter
- {
- get
- {
- if (this.xmlImporter == null)
- {
- this.xmlImporter = new XmlReflectionImporter(defaultNs);
- }
- return this.xmlImporter;
- }
- }
- Dictionary<string, XmlMembersMapping> XmlMappings
- {
- get
- {
- if (this.xmlMappings == null)
- {
- this.xmlMappings = new Dictionary<string, XmlMembersMapping>();
- }
- return this.xmlMappings;
- }
- }
- internal XmlMembersMapping ImportMembersMapping(XmlName elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, bool isEncoded, string mappingKey)
- {
- XmlMembersMapping mapping;
- string mappingName = elementName.DecodedName;
- if (XmlMappings.TryGetValue(mappingKey, out mapping))
- {
- return mapping;
- }
- if (isEncoded)
- mapping = this.SoapImporter.ImportMembersMapping(mappingName, ns, members, hasWrapperElement, rpc);
- else
- mapping = this.XmlImporter.ImportMembersMapping(mappingName, ns, members, hasWrapperElement, rpc);
- mapping.SetKey(mappingKey);
- XmlMappings.Add(mappingKey, mapping);
- return mapping;
- }
- internal XmlTypeMapping ImportTypeMapping(Type type, bool isEncoded)
- {
- if (isEncoded)
- return this.SoapImporter.ImportTypeMapping(type);
- else
- return this.XmlImporter.ImportTypeMapping(type);
- }
- internal void IncludeType(Type knownType, bool isEncoded)
- {
- if (isEncoded)
- this.SoapImporter.IncludeType(knownType);
- else
- this.XmlImporter.IncludeType(knownType);
- }
- }
- internal class SerializerGenerationContext
- {
- List<XmlMembersMapping> Mappings = new List<XmlMembersMapping>();
- XmlSerializer[] serializers = null;
- Type type;
- object thisLock = new object();
- internal SerializerGenerationContext(Type type)
- {
- this.type = type;
- }
- // returns a stub to a serializer
- internal SerializerStub AddSerializer(XmlMembersMapping mapping)
- {
- int handle = -1;
- if (mapping != null)
- {
- handle = ((IList)Mappings).Add(mapping);
- }
- return new SerializerStub(this, mapping, handle);
- }
- internal XmlSerializer GetSerializer(int handle)
- {
- if (handle < 0)
- {
- return null;
- }
- if (this.serializers == null)
- {
- lock (this.thisLock)
- {
- if (this.serializers == null)
- {
- this.serializers = GenerateSerializers();
- }
- }
- }
- return this.serializers[handle];
- }
- XmlSerializer[] GenerateSerializers()
- {
- //this.Mappings may have duplicate mappings (for e.g. samed message contract is used by more than one operation)
- //XmlSerializer.FromMappings require unique mappings. The following code uniquifies, calls FromMappings and deuniquifies
- List<XmlMembersMapping> uniqueMappings = new List<XmlMembersMapping>();
- int[] uniqueIndexes = new int[Mappings.Count];
- for (int srcIndex = 0; srcIndex < Mappings.Count; srcIndex++)
- {
- XmlMembersMapping mapping = Mappings[srcIndex];
- int uniqueIndex = uniqueMappings.IndexOf(mapping);
- if (uniqueIndex < 0)
- {
- uniqueMappings.Add(mapping);
- uniqueIndex = uniqueMappings.Count - 1;
- }
- uniqueIndexes[srcIndex] = uniqueIndex;
- }
- XmlSerializer[] uniqueSerializers = CreateSerializersFromMappings(uniqueMappings.ToArray(), type);
- if (uniqueMappings.Count == Mappings.Count)
- return uniqueSerializers;
- XmlSerializer[] serializers = new XmlSerializer[Mappings.Count];
- for (int i = 0; i < Mappings.Count; i++)
- {
- serializers[i] = uniqueSerializers[uniqueIndexes[i]];
- }
- return serializers;
- }
- [Fx.Tag.SecurityNote(Critical = "XmlSerializer.FromMappings has a LinkDemand.",
- Safe = "LinkDemand is spurious, not protecting anything in particular.")]
- [SecuritySafeCritical]
- XmlSerializer[] CreateSerializersFromMappings(XmlMapping[] mappings, Type type)
- {
- return XmlSerializer.FromMappings(mappings, type);
- }
- }
- internal struct SerializerStub
- {
- readonly SerializerGenerationContext context;
- internal readonly XmlMembersMapping Mapping;
- internal readonly int Handle;
- internal SerializerStub(SerializerGenerationContext context, XmlMembersMapping mapping, int handle)
- {
- this.context = context;
- this.Mapping = mapping;
- this.Handle = handle;
- }
- internal XmlSerializer GetSerializer()
- {
- return context.GetSerializer(Handle);
- }
- }
- internal class XmlSerializerFaultContractInfo
- {
- FaultContractInfo faultContractInfo;
- SerializerStub serializerStub;
- XmlQualifiedName faultContractElementName;
- XmlSerializerObjectSerializer serializer;
- internal XmlSerializerFaultContractInfo(FaultContractInfo faultContractInfo, SerializerStub serializerStub,
- XmlQualifiedName faultContractElementName)
- {
- if (faultContractInfo == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("faultContractInfo");
- }
- if (faultContractElementName == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("faultContractElementName");
- }
- this.faultContractInfo = faultContractInfo;
- this.serializerStub = serializerStub;
- this.faultContractElementName = faultContractElementName;
- }
- internal FaultContractInfo FaultContractInfo
- {
- get { return this.faultContractInfo; }
- }
- internal XmlQualifiedName FaultContractElementName
- {
- get { return this.faultContractElementName; }
- }
- internal XmlSerializerObjectSerializer Serializer
- {
- get
- {
- if (this.serializer == null)
- this.serializer = new XmlSerializerObjectSerializer(faultContractInfo.Detail, this.faultContractElementName, this.serializerStub.GetSerializer());
- return this.serializer;
- }
- }
- }
- internal class MessageInfo : XmlSerializerOperationFormatter.MessageInfo
- {
- SerializerStub headers;
- SerializerStub body;
- OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable;
- MessageHeaderDescription unknownHeaderDescription;
- MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts;
- internal XmlMembersMapping BodyMapping
- {
- get { return body.Mapping; }
- }
- internal override XmlSerializer BodySerializer
- {
- get { return body.GetSerializer(); }
- }
- internal XmlMembersMapping HeadersMapping
- {
- get { return headers.Mapping; }
- }
- internal override XmlSerializer HeaderSerializer
- {
- get { return headers.GetSerializer(); }
- }
- internal override OperationFormatter.MessageHeaderDescriptionTable HeaderDescriptionTable
- {
- get { return this.headerDescriptionTable; }
- }
- internal override MessageHeaderDescription UnknownHeaderDescription
- {
- get { return this.unknownHeaderDescription; }
- }
- internal override MessagePartDescriptionCollection RpcEncodedTypedMessageBodyParts
- {
- get { return rpcEncodedTypedMessageBodyParts; }
- }
- internal void SetBody(SerializerStub body, MessagePartDescriptionCollection rpcEncodedTypedMessageBodyParts)
- {
- this.body = body;
- this.rpcEncodedTypedMessageBodyParts = rpcEncodedTypedMessageBodyParts;
- }
- internal void SetHeaders(SerializerStub headers)
- {
- this.headers = headers;
- }
- internal void SetHeaderDescriptionTable(OperationFormatter.MessageHeaderDescriptionTable headerDescriptionTable)
- {
- this.headerDescriptionTable = headerDescriptionTable;
- }
- internal void SetUnknownHeaderDescription(MessageHeaderDescription unknownHeaderDescription)
- {
- this.unknownHeaderDescription = unknownHeaderDescription;
- }
- }
- }
- }
- static class XmlSerializerHelper
- {
- static internal XmlReflectionMember GetXmlReflectionMember(MessagePartDescription part, bool isRpc, bool isEncoded, bool isWrapped)
- {
- string ns = isRpc ? null : part.Namespace;
- ICustomAttributeProvider additionalAttributesProvider = null;
- if (isEncoded || part.AdditionalAttributesProvider is MemberInfo)
- additionalAttributesProvider = part.AdditionalAttributesProvider;
- XmlName memberName = string.IsNullOrEmpty(part.UniquePartName) ? null : new XmlName(part.UniquePartName, true /*isEncoded*/);
- XmlName elementName = part.XmlName;
- return GetXmlReflectionMember(memberName, elementName, ns, part.Type, additionalAttributesProvider, part.Multiple, isEncoded, isWrapped);
- }
- static internal XmlReflectionMember GetXmlReflectionMember(XmlName memberName, XmlName elementName, string ns, Type type, ICustomAttributeProvider additionalAttributesProvider, bool isMultiple, bool isEncoded, bool isWrapped)
- {
- if (isEncoded && isMultiple)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMultiplePartsNotAllowedInEncoded, elementName.DecodedName, ns)));
- XmlReflectionMember member = new XmlReflectionMember();
- member.MemberName = (memberName ?? elementName).DecodedName;
- member.MemberType = type;
- if (member.MemberType.IsByRef)
- member.MemberType = member.MemberType.GetElementType();
- if (isMultiple)
- member.MemberType = member.MemberType.MakeArrayType();
- if (additionalAttributesProvider != null)
- {
- if (isEncoded)
- member.SoapAttributes = new SoapAttributes(additionalAttributesProvider);
- else
- member.XmlAttributes = new XmlAttributes(additionalAttributesProvider);
- }
- if (isEncoded)
- {
- if (member.SoapAttributes == null)
- member.SoapAttributes = new SoapAttributes();
- else
- {
- Type invalidAttributeType = null;
- if (member.SoapAttributes.SoapAttribute != null)
- invalidAttributeType = typeof(SoapAttributeAttribute);
- else if (member.SoapAttributes.SoapIgnore)
- invalidAttributeType = typeof(SoapIgnoreAttribute);
- else if (member.SoapAttributes.SoapType != null)
- invalidAttributeType = typeof(SoapTypeAttribute);
- if (invalidAttributeType != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidSoapAttribute, invalidAttributeType, elementName.DecodedName)));
- }
- if (member.SoapAttributes.SoapElement == null)
- member.SoapAttributes.SoapElement = new SoapElementAttribute(elementName.DecodedName);
- }
- else
- {
- if (member.XmlAttributes == null)
- member.XmlAttributes = new XmlAttributes();
- else
- {
- Type invalidAttributeType = null;
- if (member.XmlAttributes.XmlAttribute != null)
- invalidAttributeType = typeof(XmlAttributeAttribute);
- else if (member.XmlAttributes.XmlAnyAttribute != null && !isWrapped)
- invalidAttributeType = typeof(XmlAnyAttributeAttribute);
- else if (member.XmlAttributes.XmlChoiceIdentifier != null)
- invalidAttributeType = typeof(XmlChoiceIdentifierAttribute);
- else if (member.XmlAttributes.XmlIgnore)
- invalidAttributeType = typeof(XmlIgnoreAttribute);
- else if (member.XmlAttributes.Xmlns)
- invalidAttributeType = typeof(XmlNamespaceDeclarationsAttribute);
- else if (member.XmlAttributes.XmlText != null)
- invalidAttributeType = typeof(XmlTextAttribute);
- else if (member.XmlAttributes.XmlEnum != null)
- invalidAttributeType = typeof(XmlEnumAttribute);
- if (invalidAttributeType != null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(isWrapped ? SR.SFxInvalidXmlAttributeInWrapped : SR.SFxInvalidXmlAttributeInBare, invalidAttributeType, elementName.DecodedName)));
- if (member.XmlAttributes.XmlArray != null && isMultiple)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxXmlArrayNotAllowedForMultiple, elementName.DecodedName, ns)));
- }
- bool isArray = member.MemberType.IsArray;
- if ((isArray && !isMultiple && member.MemberType != typeof(byte[])) ||
- (!isArray && typeof(IEnumerable).IsAssignableFrom(member.MemberType) && member.MemberType != typeof(string) && !typeof(XmlNode).IsAssignableFrom(member.MemberType) && !typeof(IXmlSerializable).IsAssignableFrom(member.MemberType)))
- {
- if (member.XmlAttributes.XmlArray != null)
- {
- if (member.XmlAttributes.XmlArray.ElementName == String.Empty)
- member.XmlAttributes.XmlArray.ElementName = elementName.DecodedName;
- if (member.XmlAttributes.XmlArray.Namespace == null)
- member.XmlAttributes.XmlArray.Namespace = ns;
- }
- else if (HasNoXmlParameterAttributes(member.XmlAttributes))
- {
- member.XmlAttributes.XmlArray = new XmlArrayAttribute();
- member.XmlAttributes.XmlArray.ElementName = elementName.DecodedName;
- member.XmlAttributes.XmlArray.Namespace = ns;
- }
- }
- else
- {
- if (member.XmlAttributes.XmlElements == null || member.XmlAttributes.XmlElements.Count == 0)
- {
- if (HasNoXmlParameterAttributes(member.XmlAttributes))
- {
- XmlElementAttribute elementAttribute = new XmlElementAttribute();
- elementAttribute.ElementName = elementName.DecodedName;
- elementAttribute.Namespace = ns;
- member.XmlAttributes.XmlElements.Add(elementAttribute);
- }
- }
- else
- {
- foreach (XmlElementAttribute elementAttribute in member.XmlAttributes.XmlElements)
- {
- if (elementAttribute.ElementName == String.Empty)
- elementAttribute.ElementName = elementName.DecodedName;
- if (elementAttribute.Namespace == null)
- elementAttribute.Namespace = ns;
- }
- }
- }
- }
- return member;
- }
- static bool HasNoXmlParameterAttributes(XmlAttributes xmlAttributes)
- {
- return xmlAttributes.XmlAnyAttribute == null &&
- (xmlAttributes.XmlAnyElements == null || xmlAttributes.XmlAnyElements.Count == 0) &&
- xmlAttributes.XmlArray == null &&
- xmlAttributes.XmlAttribute == null &&
- !xmlAttributes.XmlIgnore &&
- xmlAttributes.XmlText == null &&
- xmlAttributes.XmlChoiceIdentifier == null &&
- (xmlAttributes.XmlElements == null || xmlAttributes.XmlElements.Count == 0) &&
- !xmlAttributes.Xmlns;
- }
- }
- }
|