| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System.Collections;
- using System.ServiceModel;
- using System.ServiceModel.Description;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.IO;
- using System.Runtime.Serialization;
- using System.Reflection;
- using System.Xml;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Channels;
- using System.Runtime.Diagnostics;
- using System.Runtime;
- using System.Threading;
- abstract class OperationFormatter : IClientMessageFormatter, IDispatchMessageFormatter
- {
- MessageDescription replyDescription;
- MessageDescription requestDescription;
- XmlDictionaryString action;
- XmlDictionaryString replyAction;
- protected StreamFormatter requestStreamFormatter, replyStreamFormatter;
- XmlDictionary dictionary;
- string operationName;
- static object[] emptyObjectArray = new object[0];
- public OperationFormatter(OperationDescription description, bool isRpc, bool isEncoded)
- {
- Validate(description, isRpc, isEncoded);
- this.requestDescription = description.Messages[0];
- if (description.Messages.Count == 2)
- this.replyDescription = description.Messages[1];
- int stringCount = 3 + requestDescription.Body.Parts.Count;
- if (replyDescription != null)
- stringCount += 2 + replyDescription.Body.Parts.Count;
- dictionary = new XmlDictionary(stringCount * 2);
- GetActions(description, dictionary, out this.action, out this.replyAction);
- operationName = description.Name;
- requestStreamFormatter = StreamFormatter.Create(requestDescription, operationName, true/*isRequest*/);
- if (replyDescription != null)
- replyStreamFormatter = StreamFormatter.Create(replyDescription, operationName, false/*isResponse*/);
- }
- protected abstract void AddHeadersToMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest);
- protected abstract void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, string action, MessageDescription messageDescription, object returnValue, object[] parameters, bool isRequest);
- protected abstract void GetHeadersFromMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest);
- protected abstract object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, string action, MessageDescription messageDescription, object[] parameters, bool isRequest);
- protected virtual void WriteBodyAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- }
- internal string RequestAction
- {
- get
- {
- if (action != null)
- return action.Value;
- return null;
- }
- }
- internal string ReplyAction
- {
- get
- {
- if (replyAction != null)
- return replyAction.Value;
- return null;
- }
- }
- protected XmlDictionary Dictionary
- {
- get { return dictionary; }
- }
- protected string OperationName
- {
- get { return this.operationName; }
- }
- protected MessageDescription ReplyDescription
- {
- get { return replyDescription; }
- }
- protected MessageDescription RequestDescription
- {
- get { return requestDescription; }
- }
- protected XmlDictionaryString AddToDictionary(string s)
- {
- return AddToDictionary(dictionary, s);
- }
- public object DeserializeReply(Message message, object[] parameters)
- {
- if (message == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
- if (parameters == null)
- throw TraceUtility.ThrowHelperError(new ArgumentNullException("parameters"), message);
- try
- {
- object result = null;
- if (replyDescription.IsTypedMessage)
- {
- object typeMessageInstance = CreateTypedMessageInstance(replyDescription.MessageType);
- TypedMessageParts typedMessageParts = new TypedMessageParts(typeMessageInstance, replyDescription);
- object[] parts = new object[typedMessageParts.Count];
- GetPropertiesFromMessage(message, replyDescription, parts);
- GetHeadersFromMessage(message, replyDescription, parts, false/*isRequest*/);
- DeserializeBodyContents(message, parts, false/*isRequest*/);
- // copy values into the actual field/properties
- typedMessageParts.SetTypedMessageParts(parts);
- result = typeMessageInstance;
- }
- else
- {
- GetPropertiesFromMessage(message, replyDescription, parameters);
- GetHeadersFromMessage(message, replyDescription, parameters, false/*isRequest*/);
- result = DeserializeBodyContents(message, parameters, false/*isRequest*/);
- }
- return result;
- }
- catch (XmlException xe)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
- SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, xe.Message), xe));
- }
- catch (FormatException fe)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
- SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, fe.Message), fe));
- }
- catch (SerializationException se)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
- SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, se.Message), se));
- }
- }
- private static object CreateTypedMessageInstance(Type messageContractType)
- {
- BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.NonPublic;
- try
- {
- object typeMessageInstance = Activator.CreateInstance(
- messageContractType,
- bindingFlags,
- null, emptyObjectArray, null);
- return typeMessageInstance;
- }
- catch (MissingMethodException mme)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMessageContractRequiresDefaultConstructor, messageContractType.FullName), mme));
- }
- }
- public void DeserializeRequest(Message message, object[] parameters)
- {
- if (message == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
- if (parameters == null)
- throw TraceUtility.ThrowHelperError(new ArgumentNullException("parameters"), message);
- try
- {
- if (requestDescription.IsTypedMessage)
- {
- object typeMessageInstance = CreateTypedMessageInstance(requestDescription.MessageType);
- TypedMessageParts typedMessageParts = new TypedMessageParts(typeMessageInstance, requestDescription);
- object[] parts = new object[typedMessageParts.Count];
- GetPropertiesFromMessage(message, requestDescription, parts);
- GetHeadersFromMessage(message, requestDescription, parts, true/*isRequest*/);
- DeserializeBodyContents(message, parts, true/*isRequest*/);
- // copy values into the actual field/properties
- typedMessageParts.SetTypedMessageParts(parts);
- parameters[0] = typeMessageInstance;
- }
- else
- {
- GetPropertiesFromMessage(message, requestDescription, parameters);
- GetHeadersFromMessage(message, requestDescription, parameters, true/*isRequest*/);
- DeserializeBodyContents(message, parameters, true/*isRequest*/);
- }
- }
- catch (XmlException xe)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- OperationFormatter.CreateDeserializationFailedFault(
- SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, xe.Message),
- xe));
- }
- catch (FormatException fe)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- OperationFormatter.CreateDeserializationFailedFault(
- SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, fe.Message),
- fe));
- }
- catch (SerializationException se)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
- SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, se.Message),
- se));
- }
- }
- object DeserializeBodyContents(Message message, object[] parameters, bool isRequest)
- {
- MessageDescription messageDescription;
- StreamFormatter streamFormatter;
- SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
- if (streamFormatter != null)
- {
- object retVal = null;
- streamFormatter.Deserialize(parameters, ref retVal, message);
- return retVal;
- }
- if (message.IsEmpty)
- {
- return null;
- }
- else
- {
- XmlDictionaryReader reader = message.GetReaderAtBodyContents();
- using (reader)
- {
- object body = DeserializeBody(reader, message.Version, RequestAction, messageDescription, parameters, isRequest);
- message.ReadFromBodyContentsToEnd(reader);
- return body;
- }
- }
- }
- public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
- {
- object[] parts = null;
- if (messageVersion == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("messageVersion");
- if (parameters == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
- if (requestDescription.IsTypedMessage)
- {
- TypedMessageParts typedMessageParts = new TypedMessageParts(parameters[0], requestDescription);
- // copy values from the actual field/properties
- parts = new object[typedMessageParts.Count];
- typedMessageParts.GetTypedMessageParts(parts);
- }
- else
- {
- parts = parameters;
- }
- Message msg = new OperationFormatterMessage(this, messageVersion,
- action == null ? null : ActionHeader.Create(action, messageVersion.Addressing),
- parts, null, true/*isRequest*/);
- AddPropertiesToMessage(msg, requestDescription, parts);
- AddHeadersToMessage(msg, requestDescription, parts, true /*isRequest*/);
- return msg;
- }
- public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
- {
- object[] parts = null;
- object resultPart = null;
- if (messageVersion == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("messageVersion");
- if (parameters == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
- if (replyDescription.IsTypedMessage)
- {
- // If the response is a typed message then it must
- // me the response (as opposed to an out param). We will
- // serialize the response in the exact same way that we
- // would serialize a bunch of outs (with no return value).
- TypedMessageParts typedMessageParts = new TypedMessageParts(result, replyDescription);
- // make a copy of the list so that we have the actual values of the field/properties
- parts = new object[typedMessageParts.Count];
- typedMessageParts.GetTypedMessageParts(parts);
- resultPart = null;
- }
- else
- {
- parts = parameters;
- resultPart = result;
- }
- Message msg = new OperationFormatterMessage(this, messageVersion,
- replyAction == null ? null : ActionHeader.Create(replyAction, messageVersion.Addressing),
- parts, resultPart, false/*isRequest*/);
- AddPropertiesToMessage(msg, replyDescription, parts);
- AddHeadersToMessage(msg, replyDescription, parts, false /*isRequest*/);
- return msg;
- }
- void SetupStreamAndMessageDescription(bool isRequest, out StreamFormatter streamFormatter, out MessageDescription messageDescription)
- {
- if (isRequest)
- {
- streamFormatter = requestStreamFormatter;
- messageDescription = requestDescription;
- }
- else
- {
- streamFormatter = replyStreamFormatter;
- messageDescription = replyDescription;
- }
- }
- void SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, object[] parameters, object returnValue, bool isRequest)
- {
- MessageDescription messageDescription;
- StreamFormatter streamFormatter;
- SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
- if (streamFormatter != null)
- {
- streamFormatter.Serialize(writer, parameters, returnValue);
- return;
- }
- SerializeBody(writer, version, RequestAction, messageDescription, returnValue, parameters, isRequest);
- }
- IAsyncResult BeginSerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, object[] parameters, object returnValue, bool isRequest,
- AsyncCallback callback, object state)
- {
- return new SerializeBodyContentsAsyncResult(this, writer, version, parameters, returnValue, isRequest, callback, state);
- }
- void EndSerializeBodyContents(IAsyncResult result)
- {
- SerializeBodyContentsAsyncResult.End(result);
- }
- class SerializeBodyContentsAsyncResult : AsyncResult
- {
- static AsyncCompletion handleEndSerializeBodyContents = new AsyncCompletion(HandleEndSerializeBodyContents);
- StreamFormatter streamFormatter;
- internal SerializeBodyContentsAsyncResult(OperationFormatter operationFormatter, XmlDictionaryWriter writer, MessageVersion version, object[] parameters,
- object returnValue, bool isRequest, AsyncCallback callback, object state)
- : base(callback, state)
- {
- bool completeSelf = true;
- MessageDescription messageDescription;
- StreamFormatter streamFormatter;
- operationFormatter.SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
- if (streamFormatter != null)
- {
- this.streamFormatter = streamFormatter;
- IAsyncResult result = streamFormatter.BeginSerialize(writer, parameters, returnValue, PrepareAsyncCompletion(handleEndSerializeBodyContents), this);
- completeSelf = SyncContinue(result);
- }
- else
- {
- operationFormatter.SerializeBody(writer, version, operationFormatter.RequestAction, messageDescription, returnValue, parameters, isRequest);
- completeSelf = true;
- }
- if (completeSelf)
- {
- Complete(true);
- }
- }
- static bool HandleEndSerializeBodyContents(IAsyncResult result)
- {
- SerializeBodyContentsAsyncResult thisPtr = (SerializeBodyContentsAsyncResult)result.AsyncState;
- thisPtr.streamFormatter.EndSerialize(result);
- return true;
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<SerializeBodyContentsAsyncResult>(result);
- }
- }
- void AddPropertiesToMessage(Message message, MessageDescription messageDescription, object[] parameters)
- {
- if (messageDescription.Properties.Count > 0)
- {
- AddPropertiesToMessageCore(message, messageDescription, parameters);
- }
- }
- void AddPropertiesToMessageCore(Message message, MessageDescription messageDescription, object[] parameters)
- {
- MessageProperties properties = message.Properties;
- MessagePropertyDescriptionCollection propertyDescriptions = messageDescription.Properties;
- for (int i = 0; i < propertyDescriptions.Count; i++)
- {
- MessagePropertyDescription propertyDescription = propertyDescriptions[i];
- object parameter = parameters[propertyDescription.Index];
- if (null != parameter)
- properties.Add(propertyDescription.Name, parameter);
- }
- }
- void GetPropertiesFromMessage(Message message, MessageDescription messageDescription, object[] parameters)
- {
- if (messageDescription.Properties.Count > 0)
- {
- GetPropertiesFromMessageCore(message, messageDescription, parameters);
- }
- }
- void GetPropertiesFromMessageCore(Message message, MessageDescription messageDescription, object[] parameters)
- {
- MessageProperties properties = message.Properties;
- MessagePropertyDescriptionCollection propertyDescriptions = messageDescription.Properties;
- for (int i = 0; i < propertyDescriptions.Count; i++)
- {
- MessagePropertyDescription propertyDescription = propertyDescriptions[i];
- if (properties.ContainsKey(propertyDescription.Name))
- {
- parameters[propertyDescription.Index] = properties[propertyDescription.Name];
- }
- }
- }
- internal static object GetContentOfMessageHeaderOfT(MessageHeaderDescription headerDescription, object parameterValue, out bool mustUnderstand, out bool relay, out string actor)
- {
- actor = headerDescription.Actor;
- mustUnderstand = headerDescription.MustUnderstand;
- relay = headerDescription.Relay;
- if (headerDescription.TypedHeader && parameterValue != null)
- parameterValue = TypedHeaderManager.GetContent(headerDescription.Type, parameterValue, out mustUnderstand, out relay, out actor);
- return parameterValue;
- }
- internal static bool IsValidReturnValue(MessagePartDescription returnValue)
- {
- return (returnValue != null) && (returnValue.Type != typeof(void));
- }
- internal static XmlDictionaryString AddToDictionary(XmlDictionary dictionary, string s)
- {
- XmlDictionaryString dictionaryString;
- if (!dictionary.TryLookup(s, out dictionaryString))
- {
- dictionaryString = dictionary.Add(s);
- }
- return dictionaryString;
- }
- internal static void Validate(OperationDescription operation, bool isRpc, bool isEncoded)
- {
- if (isEncoded && !isRpc)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDocEncodedNotSupported, operation.Name)));
- }
- bool hasVoid = false;
- bool hasTypedOrUntypedMessage = false;
- bool hasParameter = false;
- for (int i = 0; i < operation.Messages.Count; i++)
- {
- MessageDescription message = operation.Messages[i];
- if (message.IsTypedMessage || message.IsUntypedMessage)
- {
- if (isRpc && operation.IsValidateRpcWrapperName)
- {
- if (!isEncoded)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedMessageCannotBeRpcLiteral, operation.Name)));
- }
- hasTypedOrUntypedMessage = true;
- }
- else if (message.IsVoid)
- hasVoid = true;
- else
- hasParameter = true;
- }
- if (hasParameter && hasTypedOrUntypedMessage)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedOrUntypedMessageCannotBeMixedWithParameters, operation.Name)));
- if (isRpc && hasTypedOrUntypedMessage && hasVoid)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedOrUntypedMessageCannotBeMixedWithVoidInRpc, operation.Name)));
- }
- internal static void GetActions(OperationDescription description, XmlDictionary dictionary, out XmlDictionaryString action, out XmlDictionaryString replyAction)
- {
- string actionString, replyActionString;
- actionString = description.Messages[0].Action;
- if (actionString == MessageHeaders.WildcardAction)
- actionString = null;
- if (!description.IsOneWay)
- replyActionString = description.Messages[1].Action;
- else
- replyActionString = null;
- if (replyActionString == MessageHeaders.WildcardAction)
- replyActionString = null;
- action = replyAction = null;
- if (actionString != null)
- action = AddToDictionary(dictionary, actionString);
- if (replyActionString != null)
- replyAction = AddToDictionary(dictionary, replyActionString);
- }
- internal static NetDispatcherFaultException CreateDeserializationFailedFault(string reason, Exception innerException)
- {
- reason = SR.GetString(SR.SFxDeserializationFailed1, reason);
- FaultCode code = new FaultCode(FaultCodeConstants.Codes.DeserializationFailed, FaultCodeConstants.Namespaces.NetDispatch);
- code = FaultCode.CreateSenderFaultCode(code);
- return new NetDispatcherFaultException(reason, code, innerException);
- }
- internal static void TraceAndSkipElement(XmlReader xmlReader)
- {
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.ElementIgnored, SR.GetString(SR.SFxTraceCodeElementIgnored), new StringTraceRecord("Element", xmlReader.NamespaceURI + ":" + xmlReader.LocalName));
- }
- xmlReader.Skip();
- }
- class TypedMessageParts
- {
- object instance;
- MemberInfo[] members;
- public TypedMessageParts(object instance, MessageDescription description)
- {
- if (description == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("description"));
- }
- if (instance == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(SR.GetString(SR.SFxTypedMessageCannotBeNull, description.Action)));
- }
- members = new MemberInfo[description.Body.Parts.Count + description.Properties.Count + description.Headers.Count];
- foreach (MessagePartDescription part in description.Headers)
- members[part.Index] = part.MemberInfo;
- foreach (MessagePartDescription part in description.Properties)
- members[part.Index] = part.MemberInfo;
- foreach (MessagePartDescription part in description.Body.Parts)
- members[part.Index] = part.MemberInfo;
- this.instance = instance;
- }
- object GetValue(int index)
- {
- MemberInfo memberInfo = members[index];
- if (memberInfo.MemberType == MemberTypes.Property)
- {
- return ((PropertyInfo)members[index]).GetValue(instance, null);
- }
- else
- {
- return ((FieldInfo)members[index]).GetValue(instance);
- }
- }
- void SetValue(object value, int index)
- {
- MemberInfo memberInfo = members[index];
- if (memberInfo.MemberType == MemberTypes.Property)
- {
- ((PropertyInfo)members[index]).SetValue(instance, value, null);
- }
- else
- {
- ((FieldInfo)members[index]).SetValue(instance, value);
- }
- }
- internal void GetTypedMessageParts(object[] values)
- {
- for (int i = 0; i < this.members.Length; i++)
- {
- values[i] = GetValue(i);
- }
- }
- internal void SetTypedMessageParts(object[] values)
- {
- for (int i = 0; i < this.members.Length; i++)
- {
- SetValue(values[i], i);
- }
- }
- internal int Count
- {
- get { return this.members.Length; }
- }
- }
- internal class OperationFormatterMessage : BodyWriterMessage
- {
- OperationFormatter operationFormatter;
- public OperationFormatterMessage(OperationFormatter operationFormatter, MessageVersion version, ActionHeader action,
- object[] parameters, object returnValue, bool isRequest)
- : base(version, action, new OperationFormatterBodyWriter(operationFormatter, version, parameters, returnValue, isRequest))
- {
- this.operationFormatter = operationFormatter;
- }
- public OperationFormatterMessage(MessageVersion version, string action, BodyWriter bodyWriter) : base(version, action, bodyWriter) { }
- OperationFormatterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, OperationFormatterBodyWriter bodyWriter)
- : base(headers, properties, bodyWriter)
- {
- operationFormatter = bodyWriter.OperationFormatter;
- }
- protected override void OnWriteStartBody(XmlDictionaryWriter writer)
- {
- base.OnWriteStartBody(writer);
- operationFormatter.WriteBodyAttributes(writer, this.Version);
- }
- protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
- {
- BodyWriter bufferedBodyWriter;
- if (BodyWriter.IsBuffered)
- {
- bufferedBodyWriter = base.BodyWriter;
- }
- else
- {
- bufferedBodyWriter = base.BodyWriter.CreateBufferedCopy(maxBufferSize);
- }
- KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[base.Properties.Count];
- ((ICollection<KeyValuePair<string, object>>)base.Properties).CopyTo(properties, 0);
- return new OperationFormatterMessageBuffer(base.Headers, properties, bufferedBodyWriter);
- }
- class OperationFormatterBodyWriter : BodyWriter
- {
- bool isRequest;
- OperationFormatter operationFormatter;
- object[] parameters;
- object returnValue;
- MessageVersion version;
- bool onBeginWriteBodyContentsCalled;
- public OperationFormatterBodyWriter(OperationFormatter operationFormatter, MessageVersion version,
- object[] parameters, object returnValue, bool isRequest)
- : base(AreParametersBuffered(isRequest, operationFormatter))
- {
- this.parameters = parameters;
- this.returnValue = returnValue;
- this.isRequest = isRequest;
- this.operationFormatter = operationFormatter;
- this.version = version;
- }
- object ThisLock
- {
- get { return this; }
- }
- static bool AreParametersBuffered(bool isRequest, OperationFormatter operationFormatter)
- {
- StreamFormatter streamFormatter = isRequest ? operationFormatter.requestStreamFormatter : operationFormatter.replyStreamFormatter;
- return streamFormatter == null;
- }
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- lock (ThisLock)
- {
- this.operationFormatter.SerializeBodyContents(writer, this.version, this.parameters, this.returnValue, this.isRequest);
- }
- }
- protected override IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
- {
- Fx.Assert(!onBeginWriteBodyContentsCalled, "OnBeginWriteBodyContents has already been called");
- this.onBeginWriteBodyContentsCalled = true;
- return new OnWriteBodyContentsAsyncResult(this, writer, callback, state);
- }
- protected override void OnEndWriteBodyContents(IAsyncResult result)
- {
- OnWriteBodyContentsAsyncResult.End(result);
- }
- internal OperationFormatter OperationFormatter
- {
- get { return operationFormatter; }
- }
- class OnWriteBodyContentsAsyncResult : AsyncResult
- {
- static AsyncCompletion handleEndOnWriteBodyContents = new AsyncCompletion(HandleEndOnWriteBodyContents);
- OperationFormatter operationFormatter;
- internal OnWriteBodyContentsAsyncResult(OperationFormatterBodyWriter operationFormatterBodyWriter, XmlDictionaryWriter writer, AsyncCallback callback, object state)
- : base(callback, state)
- {
- bool completeSelf = true;
- this.operationFormatter = operationFormatterBodyWriter.OperationFormatter;
- IAsyncResult result = this.operationFormatter.BeginSerializeBodyContents(writer, operationFormatterBodyWriter.version,
- operationFormatterBodyWriter.parameters, operationFormatterBodyWriter.returnValue, operationFormatterBodyWriter.isRequest,
- PrepareAsyncCompletion(handleEndOnWriteBodyContents), this);
- completeSelf = SyncContinue(result);
- if (completeSelf)
- {
- Complete(true);
- }
- }
- static bool HandleEndOnWriteBodyContents(IAsyncResult result)
- {
- OnWriteBodyContentsAsyncResult thisPtr = (OnWriteBodyContentsAsyncResult)result.AsyncState;
- thisPtr.operationFormatter.EndSerializeBodyContents(result);
- return true;
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<OnWriteBodyContentsAsyncResult>(result);
- }
- }
- }
- class OperationFormatterMessageBuffer : BodyWriterMessageBuffer
- {
- public OperationFormatterMessageBuffer(MessageHeaders headers,
- KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
- : base(headers, properties, bodyWriter)
- {
- }
- public override Message CreateMessage()
- {
- OperationFormatterBodyWriter operationFormatterBodyWriter = base.BodyWriter as OperationFormatterBodyWriter;
- if (operationFormatterBodyWriter == null)
- return base.CreateMessage();
- lock (ThisLock)
- {
- if (base.Closed)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
- return new OperationFormatterMessage(base.Headers, base.Properties, operationFormatterBodyWriter);
- }
- }
- }
- }
- internal abstract class OperationFormatterHeader : MessageHeader
- {
- protected MessageHeader innerHeader; //use innerHeader to handle versionSupported, actor/role handling etc.
- protected OperationFormatter operationFormatter;
- protected MessageVersion version;
- public OperationFormatterHeader(OperationFormatter operationFormatter, MessageVersion version, string name, string ns, bool mustUnderstand, string actor, bool relay)
- {
- this.operationFormatter = operationFormatter;
- this.version = version;
- if (actor != null)
- innerHeader = MessageHeader.CreateHeader(name, ns, null/*headerValue*/, mustUnderstand, actor, relay);
- else
- innerHeader = MessageHeader.CreateHeader(name, ns, null/*headerValue*/, mustUnderstand, "", relay);
- }
- public override bool IsMessageVersionSupported(MessageVersion messageVersion)
- {
- return innerHeader.IsMessageVersionSupported(messageVersion);
- }
- public override string Name
- {
- get { return innerHeader.Name; }
- }
- public override string Namespace
- {
- get { return innerHeader.Namespace; }
- }
- public override bool MustUnderstand
- {
- get { return innerHeader.MustUnderstand; }
- }
- public override bool Relay
- {
- get { return innerHeader.Relay; }
- }
- public override string Actor
- {
- get { return innerHeader.Actor; }
- }
- protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- //Prefix needed since there may be xsi:type attribute at toplevel with qname value where ns = ""
- writer.WriteStartElement((this.Namespace == null || this.Namespace.Length == 0) ? string.Empty : "h", this.Name, this.Namespace);
- OnWriteHeaderAttributes(writer, messageVersion);
- }
- protected virtual void OnWriteHeaderAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- base.WriteHeaderAttributes(writer, messageVersion);
- }
- }
- internal class XmlElementMessageHeader : OperationFormatterHeader
- {
- protected XmlElement headerValue;
- public XmlElementMessageHeader(OperationFormatter operationFormatter, MessageVersion version, string name, string ns, bool mustUnderstand, string actor, bool relay, XmlElement headerValue) :
- base(operationFormatter, version, name, ns, mustUnderstand, actor, relay)
- {
- this.headerValue = headerValue;
- }
- protected override void OnWriteHeaderAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- base.WriteHeaderAttributes(writer, messageVersion);
- XmlDictionaryReader nodeReader = XmlDictionaryReader.CreateDictionaryReader(new XmlNodeReader(headerValue));
- nodeReader.MoveToContent();
- writer.WriteAttributes(nodeReader, false);
- }
- protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
- {
- headerValue.WriteContentTo(writer);
- }
- }
- internal struct QName
- {
- internal string Name;
- internal string Namespace;
- internal QName(string name, string ns)
- {
- Name = name;
- Namespace = ns;
- }
- }
- internal class QNameComparer : IEqualityComparer<QName>
- {
- static internal QNameComparer Singleton = new QNameComparer();
- QNameComparer() { }
- public bool Equals(QName x, QName y)
- {
- return x.Name == y.Name && x.Namespace == y.Namespace;
- }
- public int GetHashCode(QName obj)
- {
- return obj.Name.GetHashCode();
- }
- }
- internal class MessageHeaderDescriptionTable : Dictionary<QName, MessageHeaderDescription>
- {
- internal MessageHeaderDescriptionTable() : base(QNameComparer.Singleton) { }
- internal void Add(string name, string ns, MessageHeaderDescription message)
- {
- base.Add(new QName(name, ns), message);
- }
- internal MessageHeaderDescription Get(string name, string ns)
- {
- MessageHeaderDescription message;
- if (base.TryGetValue(new QName(name, ns), out message))
- return message;
- return null;
- }
- }
- }
- }
|