| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.Xml;
- using System.Linq;
- static class DataContractSerializerDefaults
- {
- internal const bool IgnoreExtensionDataObject = false;
- internal const int MaxItemsInObjectGraph = int.MaxValue;
- internal static DataContractSerializer CreateSerializer(Type type, int maxItems)
- {
- return CreateSerializer(type, null, maxItems);
- }
- internal static DataContractSerializer CreateSerializer(Type type, IList<Type> knownTypes, int maxItems)
- {
- return new DataContractSerializer(
- type,
- knownTypes,
- maxItems,
- DataContractSerializerDefaults.IgnoreExtensionDataObject,
- false/*preserveObjectReferences*/,
- null/*dataContractSurrage*/);
- }
- internal static DataContractSerializer CreateSerializer(Type type, string rootName, string rootNs, int maxItems)
- {
- return CreateSerializer(type, null, rootName, rootNs, maxItems);
- }
- internal static DataContractSerializer CreateSerializer(Type type, IList<Type> knownTypes, string rootName, string rootNs, int maxItems)
- {
- return new DataContractSerializer(
- type,
- rootName,
- rootNs,
- knownTypes,
- maxItems,
- DataContractSerializerDefaults.IgnoreExtensionDataObject,
- false/*preserveObjectReferences*/,
- null/*dataContractSurrage*/);
- }
- internal static DataContractSerializer CreateSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNs, int maxItems)
- {
- return CreateSerializer(type, null, rootName, rootNs, maxItems);
- }
- internal static DataContractSerializer CreateSerializer(Type type, IList<Type> knownTypes, XmlDictionaryString rootName, XmlDictionaryString rootNs, int maxItems)
- {
- return new DataContractSerializer(
- type,
- rootName,
- rootNs,
- knownTypes,
- maxItems,
- DataContractSerializerDefaults.IgnoreExtensionDataObject,
- false/*preserveObjectReferences*/,
- null/*dataContractSurrage*/);
- }
- }
- class DataContractSerializerOperationFormatter : OperationFormatter
- {
- static Type typeOfIQueryable = typeof(IQueryable);
- static Type typeOfIQueryableGeneric = typeof(IQueryable<>);
- static Type typeOfIEnumerable = typeof(IEnumerable);
- static Type typeOfIEnumerableGeneric = typeof(IEnumerable<>);
- protected MessageInfo requestMessageInfo;
- protected MessageInfo replyMessageInfo;
- IList<Type> knownTypes;
- XsdDataContractExporter dataContractExporter;
- DataContractSerializerOperationBehavior serializerFactory;
- public DataContractSerializerOperationFormatter(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute,
- DataContractSerializerOperationBehavior serializerFactory)
- : base(description, dataContractFormatAttribute.Style == OperationFormatStyle.Rpc, false/*isEncoded*/)
- {
- if (description == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
- this.serializerFactory = serializerFactory ?? new DataContractSerializerOperationBehavior(description);
- foreach (Type type in description.KnownTypes)
- {
- if (knownTypes == null)
- knownTypes = new List<Type>();
- if (type == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxKnownTypeNull, description.Name)));
- ValidateDataContractType(type);
- knownTypes.Add(type);
- }
- requestMessageInfo = CreateMessageInfo(dataContractFormatAttribute, RequestDescription, this.serializerFactory);
- if (ReplyDescription != null)
- replyMessageInfo = CreateMessageInfo(dataContractFormatAttribute, ReplyDescription, this.serializerFactory);
- }
- MessageInfo CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute,
- MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory)
- {
- if (messageDescription.IsUntypedMessage)
- return null;
- MessageInfo messageInfo = new MessageInfo();
- MessageBodyDescription body = messageDescription.Body;
- if (body.WrapperName != null)
- {
- messageInfo.WrapperName = AddToDictionary(body.WrapperName);
- messageInfo.WrapperNamespace = AddToDictionary(body.WrapperNamespace);
- }
- MessagePartDescriptionCollection parts = body.Parts;
- messageInfo.BodyParts = new PartInfo[parts.Count];
- for (int i = 0; i < parts.Count; i++)
- messageInfo.BodyParts[i] = CreatePartInfo(parts[i], dataContractFormatAttribute.Style, serializerFactory);
- if (IsValidReturnValue(messageDescription.Body.ReturnValue))
- messageInfo.ReturnPart = CreatePartInfo(messageDescription.Body.ReturnValue, dataContractFormatAttribute.Style, serializerFactory);
- messageInfo.HeaderDescriptionTable = new MessageHeaderDescriptionTable();
- messageInfo.HeaderParts = new PartInfo[messageDescription.Headers.Count];
- for (int i = 0; i < messageDescription.Headers.Count; i++)
- {
- MessageHeaderDescription headerDescription = messageDescription.Headers[i];
- if (headerDescription.IsUnknownHeaderCollection)
- messageInfo.UnknownHeaderDescription = headerDescription;
- else
- {
- ValidateDataContractType(headerDescription.Type);
- messageInfo.HeaderDescriptionTable.Add(headerDescription.Name, headerDescription.Namespace, headerDescription);
- }
- messageInfo.HeaderParts[i] = CreatePartInfo(headerDescription, OperationFormatStyle.Document, serializerFactory);
- }
- messageInfo.AnyHeaders = messageInfo.UnknownHeaderDescription != null || messageInfo.HeaderDescriptionTable.Count > 0;
- return messageInfo;
- }
- private void ValidateDataContractType(Type type)
- {
- if (dataContractExporter == null)
- {
- dataContractExporter = new XsdDataContractExporter();
- if (serializerFactory != null && serializerFactory.DataContractSurrogate != null)
- {
- ExportOptions options = new ExportOptions();
- options.DataContractSurrogate = serializerFactory.DataContractSurrogate;
- dataContractExporter.Options = options;
- }
- }
- dataContractExporter.GetSchemaTypeName(type); //Throws if the type is not a valid data contract
- }
- PartInfo CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory)
- {
- string ns = (style == OperationFormatStyle.Rpc || part.Namespace == null) ? string.Empty : part.Namespace;
- PartInfo partInfo = new PartInfo(part, AddToDictionary(part.Name), AddToDictionary(ns), knownTypes, serializerFactory);
- ValidateDataContractType(partInfo.ContractType);
- return partInfo;
- }
- protected override void AddHeadersToMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest)
- {
- MessageInfo messageInfo = isRequest ? requestMessageInfo : replyMessageInfo;
- PartInfo[] headerParts = messageInfo.HeaderParts;
- if (headerParts == null || headerParts.Length == 0)
- return;
- MessageHeaders headers = message.Headers;
- for (int i = 0; i < headerParts.Length; i++)
- {
- PartInfo headerPart = headerParts[i];
- MessageHeaderDescription headerDescription = (MessageHeaderDescription)headerPart.Description;
- object headerValue = parameters[headerDescription.Index];
- if (headerDescription.Multiple)
- {
- if (headerValue != null)
- {
- bool isXmlElement = headerDescription.Type == typeof(XmlElement);
- foreach (object headerItemValue in (IEnumerable)headerValue)
- AddMessageHeaderForParameter(headers, headerPart, message.Version, headerItemValue, isXmlElement);
- }
- }
- else
- AddMessageHeaderForParameter(headers, headerPart, message.Version, headerValue, false/*isXmlElement*/);
- }
- }
- void AddMessageHeaderForParameter(MessageHeaders headers, PartInfo headerPart, MessageVersion messageVersion, object parameterValue, bool isXmlElement)
- {
- string actor;
- bool mustUnderstand;
- bool relay;
- MessageHeaderDescription headerDescription = (MessageHeaderDescription)headerPart.Description;
- object valueToSerialize = GetContentOfMessageHeaderOfT(headerDescription, parameterValue, out mustUnderstand, out relay, out actor);
- if (isXmlElement)
- {
- if (valueToSerialize == null)
- return;
- XmlElement xmlElement = (XmlElement)valueToSerialize;
- headers.Add(new XmlElementMessageHeader(this, messageVersion, xmlElement.LocalName, xmlElement.NamespaceURI, mustUnderstand, actor, relay, xmlElement));
- return;
- }
- headers.Add(new DataContractSerializerMessageHeader(headerPart, valueToSerialize, mustUnderstand, actor, relay));
- }
- protected override void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, string action, MessageDescription messageDescription, object returnValue, object[] parameters, bool isRequest)
- {
- if (writer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("writer"));
- if (parameters == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parameters"));
- MessageInfo messageInfo;
- if (isRequest)
- messageInfo = requestMessageInfo;
- else
- messageInfo = replyMessageInfo;
- if (messageInfo.WrapperName != null)
- writer.WriteStartElement(messageInfo.WrapperName, messageInfo.WrapperNamespace);
- if (messageInfo.ReturnPart != null)
- SerializeParameter(writer, messageInfo.ReturnPart, returnValue);
- SerializeParameters(writer, messageInfo.BodyParts, parameters);
- if (messageInfo.WrapperName != null)
- writer.WriteEndElement();
- }
- void SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, object[] parameters)
- {
- for (int i = 0; i < parts.Length; i++)
- {
- PartInfo part = parts[i];
- object graph = parameters[part.Description.Index];
- SerializeParameter(writer, part, graph);
- }
- }
- void SerializeParameter(XmlDictionaryWriter writer, PartInfo part, object graph)
- {
- if (part.Description.Multiple)
- {
- if (graph != null)
- {
- foreach (object item in (IEnumerable)graph)
- SerializeParameterPart(writer, part, item);
- }
- }
- else
- SerializeParameterPart(writer, part, graph);
- }
- void SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, object graph)
- {
- try
- {
- part.Serializer.WriteObject(writer, graph);
- }
- catch (SerializationException sx)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
- SR.GetString(SR.SFxInvalidMessageBodyErrorSerializingParameter, part.Description.Namespace, part.Description.Name, sx.Message), sx));
- }
- }
- protected override void GetHeadersFromMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest)
- {
- MessageInfo messageInfo = isRequest ? requestMessageInfo : replyMessageInfo;
- if (!messageInfo.AnyHeaders)
- return;
- MessageHeaders headers = message.Headers;
- KeyValuePair<Type, ArrayList>[] multipleHeaderValues = null;
- ArrayList elementList = null;
- if (messageInfo.UnknownHeaderDescription != null)
- elementList = new ArrayList();
- for (int i = 0; i < headers.Count; i++)
- {
- MessageHeaderInfo header = headers[i];
- MessageHeaderDescription headerDescription = messageInfo.HeaderDescriptionTable.Get(header.Name, header.Namespace);
- if (headerDescription != null)
- {
- if (header.MustUnderstand)
- headers.UnderstoodHeaders.Add(header);
- object item = null;
- XmlDictionaryReader headerReader = headers.GetReaderAtHeader(i);
- try
- {
- object dataValue = DeserializeHeaderContents(headerReader, messageDescription, headerDescription);
- if (headerDescription.TypedHeader)
- item = TypedHeaderManager.Create(headerDescription.Type, dataValue, headers[i].MustUnderstand, headers[i].Relay, headers[i].Actor);
- else
- item = dataValue;
- }
- finally
- {
- headerReader.Close();
- }
- if (headerDescription.Multiple)
- {
- if (multipleHeaderValues == null)
- multipleHeaderValues = new KeyValuePair<Type, ArrayList>[parameters.Length];
- if (multipleHeaderValues[headerDescription.Index].Key == null)
- {
- multipleHeaderValues[headerDescription.Index] = new KeyValuePair<System.Type, System.Collections.ArrayList>(headerDescription.TypedHeader ? TypedHeaderManager.GetMessageHeaderType(headerDescription.Type) : headerDescription.Type, new ArrayList());
- }
- multipleHeaderValues[headerDescription.Index].Value.Add(item);
- }
- else
- parameters[headerDescription.Index] = item;
- }
- else if (messageInfo.UnknownHeaderDescription != null)
- {
- MessageHeaderDescription unknownHeaderDescription = messageInfo.UnknownHeaderDescription;
- XmlDictionaryReader headerReader = headers.GetReaderAtHeader(i);
- try
- {
- XmlDocument doc = new XmlDocument();
- object dataValue = doc.ReadNode(headerReader);
- if (dataValue != null && unknownHeaderDescription.TypedHeader)
- dataValue = TypedHeaderManager.Create(unknownHeaderDescription.Type, dataValue, headers[i].MustUnderstand, headers[i].Relay, headers[i].Actor);
- elementList.Add(dataValue);
- }
- finally
- {
- headerReader.Close();
- }
- }
- }
- if (multipleHeaderValues != null)
- {
- for (int i = 0; i < parameters.Length; i++)
- {
- if (multipleHeaderValues[i].Key != null)
- parameters[i] = multipleHeaderValues[i].Value.ToArray(multipleHeaderValues[i].Key);
- }
- }
- if (messageInfo.UnknownHeaderDescription != null)
- parameters[messageInfo.UnknownHeaderDescription.Index] = elementList.ToArray(messageInfo.UnknownHeaderDescription.TypedHeader ? typeof(MessageHeader<XmlElement>) : typeof(XmlElement));
- }
- object DeserializeHeaderContents(XmlDictionaryReader reader, MessageDescription messageDescription, MessageHeaderDescription headerDescription)
- {
- bool isQueryable;
- Type dataContractType = DataContractSerializerOperationFormatter.GetSubstituteDataContractType(headerDescription.Type, out isQueryable);
- XmlObjectSerializer serializerLocal = serializerFactory.CreateSerializer(dataContractType, headerDescription.Name, headerDescription.Namespace, this.knownTypes);
- object val = serializerLocal.ReadObject(reader);
- if (isQueryable && val != null)
- {
- return Queryable.AsQueryable((IEnumerable)val);
- }
- return val;
- }
- protected override object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, string action, MessageDescription messageDescription, object[] parameters, bool isRequest)
- {
- if (reader == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reader"));
- if (parameters == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parameters"));
- MessageInfo messageInfo;
- if (isRequest)
- messageInfo = requestMessageInfo;
- else
- messageInfo = replyMessageInfo;
- if (messageInfo.WrapperName != null)
- {
- if (!reader.IsStartElement(messageInfo.WrapperName, messageInfo.WrapperNamespace))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.SFxInvalidMessageBody, messageInfo.WrapperName, messageInfo.WrapperNamespace, reader.NodeType, reader.Name, reader.NamespaceURI)));
- bool isEmptyElement = reader.IsEmptyElement;
- reader.Read();
- if (isEmptyElement)
- return null;
- }
- object returnValue = null;
- if (messageInfo.ReturnPart != null)
- {
- while (true)
- {
- PartInfo part = messageInfo.ReturnPart;
- if (part.Serializer.IsStartObject(reader))
- {
- returnValue = DeserializeParameter(reader, part, isRequest);
- break;
- }
- if (!reader.IsStartElement())
- break;
- OperationFormatter.TraceAndSkipElement(reader);
- }
- }
- DeserializeParameters(reader, messageInfo.BodyParts, parameters, isRequest);
- if (messageInfo.WrapperName != null)
- reader.ReadEndElement();
- return returnValue;
- }
- void DeserializeParameters(XmlDictionaryReader reader, PartInfo[] parts, object[] parameters, bool isRequest)
- {
- int nextPartIndex = 0;
- while (reader.IsStartElement())
- {
- for (int i = nextPartIndex; i < parts.Length; i++)
- {
- PartInfo part = parts[i];
- if (part.Serializer.IsStartObject(reader))
- {
- object parameterValue = DeserializeParameter(reader, part, isRequest);
- parameters[part.Description.Index] = parameterValue;
- nextPartIndex = i + 1;
- }
- else
- parameters[part.Description.Index] = null;
- }
- if (reader.IsStartElement())
- OperationFormatter.TraceAndSkipElement(reader);
- }
- }
- object DeserializeParameter(XmlDictionaryReader reader, PartInfo part, bool isRequest)
- {
- if (part.Description.Multiple)
- {
- ArrayList items = new ArrayList();
- while (part.Serializer.IsStartObject(reader))
- items.Add(DeserializeParameterPart(reader, part, isRequest));
- return items.ToArray(part.Description.Type);
- }
- return DeserializeParameterPart(reader, part, isRequest);
- }
- object DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, bool isRequest)
- {
- object val;
- try
- {
- val = part.ReadObject(reader);
- }
- catch (System.InvalidOperationException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e));
- }
- catch (System.Runtime.Serialization.InvalidDataContractException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(
- SR.GetString(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e));
- }
- catch (System.FormatException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- OperationFormatter.CreateDeserializationFailedFault(
- SR.GetString(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore,
- part.Description.Namespace, part.Description.Name, e.Message),
- e));
- }
- catch (System.Runtime.Serialization.SerializationException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- OperationFormatter.CreateDeserializationFailedFault(
- SR.GetString(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore,
- part.Description.Namespace, part.Description.Name, e.Message),
- e));
- }
- return val;
- }
- internal static Type GetSubstituteDataContractType(Type type, out bool isQueryable)
- {
- if (type == typeOfIQueryable)
- {
- isQueryable = true;
- return typeOfIEnumerable;
- }
- if (type.IsGenericType &&
- type.GetGenericTypeDefinition() == typeOfIQueryableGeneric)
- {
- isQueryable = true;
- return typeOfIEnumerableGeneric.MakeGenericType(type.GetGenericArguments());
- }
- isQueryable = false;
- return type;
- }
- class DataContractSerializerMessageHeader : XmlObjectSerializerHeader
- {
- PartInfo headerPart;
- public DataContractSerializerMessageHeader(PartInfo headerPart, object headerValue, bool mustUnderstand, string actor, bool relay)
- : base(headerPart.DictionaryName.Value, headerPart.DictionaryNamespace.Value, headerValue, headerPart.Serializer, mustUnderstand, actor ?? string.Empty, relay)
- {
- this.headerPart = headerPart;
- }
- protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- //Prefix needed since there may be xsi:type attribute at toplevel with qname value where ns = ""
- string prefix = (this.Namespace == null || this.Namespace.Length == 0) ? string.Empty : "h";
- writer.WriteStartElement(prefix, headerPart.DictionaryName, headerPart.DictionaryNamespace);
- WriteHeaderAttributes(writer, messageVersion);
- }
- }
- protected class MessageInfo
- {
- internal PartInfo[] HeaderParts;
- internal XmlDictionaryString WrapperName;
- internal XmlDictionaryString WrapperNamespace;
- internal PartInfo[] BodyParts;
- internal PartInfo ReturnPart;
- internal MessageHeaderDescriptionTable HeaderDescriptionTable;
- internal MessageHeaderDescription UnknownHeaderDescription;
- internal bool AnyHeaders;
- }
- protected class PartInfo
- {
- XmlDictionaryString dictionaryName;
- XmlDictionaryString dictionaryNamespace;
- MessagePartDescription description;
- XmlObjectSerializer serializer;
- IList<Type> knownTypes;
- DataContractSerializerOperationBehavior serializerFactory;
- Type contractType;
- bool isQueryable;
- public PartInfo(MessagePartDescription description, XmlDictionaryString dictionaryName, XmlDictionaryString dictionaryNamespace,
- IList<Type> knownTypes, DataContractSerializerOperationBehavior behavior)
- {
- this.dictionaryName = dictionaryName;
- this.dictionaryNamespace = dictionaryNamespace;
- this.description = description;
- this.knownTypes = knownTypes;
- this.serializerFactory = behavior;
- this.contractType = DataContractSerializerOperationFormatter.GetSubstituteDataContractType(description.Type, out this.isQueryable);
- }
- public Type ContractType
- {
- get { return this.contractType; }
- }
- public MessagePartDescription Description
- {
- get { return description; }
- }
- public XmlDictionaryString DictionaryName
- {
- get { return dictionaryName; }
- }
- public XmlDictionaryString DictionaryNamespace
- {
- get { return dictionaryNamespace; }
- }
- public XmlObjectSerializer Serializer
- {
- get
- {
- if (serializer == null)
- {
- serializer = serializerFactory.CreateSerializer(contractType, DictionaryName, DictionaryNamespace, knownTypes);
- }
- return serializer;
- }
- }
- public object ReadObject(XmlDictionaryReader reader)
- {
- return this.ReadObject(reader, this.Serializer);
- }
- public object ReadObject(XmlDictionaryReader reader, XmlObjectSerializer serializer)
- {
- object val = this.serializer.ReadObject(reader, false /* verifyObjectName */);
- if (this.isQueryable && val != null)
- {
- return Queryable.AsQueryable((IEnumerable)val);
- }
- return val;
- }
- }
- }
- }
|