| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.Runtime.Serialization;
- using System.Xml;
- using System.Reflection;
- using System.Diagnostics;
- using System.Runtime;
- namespace System.ServiceModel.Dispatcher
- {
- class FaultFormatter : IClientFaultFormatter, IDispatchFaultFormatter
- {
- FaultContractInfo[] faultContractInfos;
- internal FaultFormatter(Type[] detailTypes)
- {
- List<FaultContractInfo> faultContractInfoList = new List<FaultContractInfo>();
- for (int i = 0; i < detailTypes.Length; i++)
- faultContractInfoList.Add(new FaultContractInfo(MessageHeaders.WildcardAction, detailTypes[i]));
- AddInfrastructureFaults(faultContractInfoList);
- faultContractInfos = GetSortedArray(faultContractInfoList);
- }
- internal FaultFormatter(SynchronizedCollection<FaultContractInfo> faultContractInfoCollection)
- {
- List<FaultContractInfo> faultContractInfoList;
- lock (faultContractInfoCollection.SyncRoot)
- {
- faultContractInfoList = new List<FaultContractInfo>(faultContractInfoCollection);
- }
- AddInfrastructureFaults(faultContractInfoList);
- this.faultContractInfos = GetSortedArray(faultContractInfoList);
- }
- public MessageFault Serialize(FaultException faultException, out string action)
- {
- XmlObjectSerializer serializer = null;
- Type detailType = null;
- string faultExceptionAction = action = faultException.Action;
- Type faultExceptionOfT = null;
- for (Type faultType = faultException.GetType(); faultType != typeof(FaultException); faultType = faultType.BaseType)
- {
- if (faultType.IsGenericType && (faultType.GetGenericTypeDefinition() == typeof(FaultException<>)))
- {
- faultExceptionOfT = faultType;
- break;
- }
- }
- if (faultExceptionOfT != null)
- {
- detailType = faultExceptionOfT.GetGenericArguments()[0];
- serializer = GetSerializer(detailType, faultExceptionAction, out action);
- }
- return CreateMessageFault(serializer, faultException, detailType);
- }
- public FaultException Deserialize(MessageFault messageFault, string action)
- {
- if (!messageFault.HasDetail)
- return new FaultException(messageFault, action);
- return CreateFaultException(messageFault, action);
- }
- protected virtual XmlObjectSerializer GetSerializer(Type detailType, string faultExceptionAction, out string action)
- {
- action = faultExceptionAction;
- FaultContractInfo faultInfo = null;
- for (int i = 0; i < faultContractInfos.Length; i++)
- {
- if (faultContractInfos[i].Detail == detailType)
- {
- faultInfo = faultContractInfos[i];
- break;
- }
- }
- if (faultInfo != null)
- {
- if (action == null)
- action = faultInfo.Action;
- return faultInfo.Serializer;
- }
- else
- return DataContractSerializerDefaults.CreateSerializer(detailType, int.MaxValue /* maxItemsInObjectGraph */ );
- }
- protected virtual FaultException CreateFaultException(MessageFault messageFault, string action)
- {
- IList<FaultContractInfo> faultInfos;
- if (action != null)
- {
- faultInfos = new List<FaultContractInfo>();
- for (int i = 0; i < faultContractInfos.Length; i++)
- {
- if (faultContractInfos[i].Action == action || faultContractInfos[i].Action == MessageHeaders.WildcardAction)
- {
- faultInfos.Add(faultContractInfos[i]);
- }
- }
- }
- else
- {
- faultInfos = faultContractInfos;
- }
- Type detailType = null;
- object detailObj = null;
- for (int i = 0; i < faultInfos.Count; i++)
- {
- FaultContractInfo faultInfo = faultInfos[i];
- XmlDictionaryReader detailReader = messageFault.GetReaderAtDetailContents();
- XmlObjectSerializer serializer = faultInfo.Serializer;
- if (serializer.IsStartObject(detailReader))
- {
- detailType = faultInfo.Detail;
- try
- {
- detailObj = serializer.ReadObject(detailReader);
- FaultException faultException = CreateFaultException(messageFault, action,
- detailObj, detailType, detailReader);
- if (faultException != null)
- return faultException;
- }
- catch (SerializationException)
- {
- }
- }
- }
- return new FaultException(messageFault, action);
- }
- protected FaultException CreateFaultException(MessageFault messageFault, string action,
- object detailObj, Type detailType, XmlDictionaryReader detailReader)
- {
- if (!detailReader.EOF)
- {
- detailReader.MoveToContent();
- if (detailReader.NodeType != XmlNodeType.EndElement && !detailReader.EOF)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.ExtraContentIsPresentInFaultDetail)));
- }
- bool isDetailObjectValid = true;
- if (detailObj == null)
- {
- isDetailObjectValid = !detailType.IsValueType;
- }
- else
- {
- isDetailObjectValid = detailType.IsAssignableFrom(detailObj.GetType());
- }
- if (isDetailObjectValid)
- {
- Type knownFaultType = typeof(FaultException<>).MakeGenericType(detailType);
- return (FaultException)Activator.CreateInstance(knownFaultType,
- detailObj,
- messageFault.Reason,
- messageFault.Code,
- action);
- }
- return null;
- }
- static FaultContractInfo[] GetSortedArray(List<FaultContractInfo> faultContractInfoList)
- {
- FaultContractInfo[] temp = faultContractInfoList.ToArray();
- Array.Sort<FaultContractInfo>(temp,
- delegate(FaultContractInfo x, FaultContractInfo y)
- { return string.CompareOrdinal(x.Action, y.Action); }
- );
- return temp;
- }
- static void AddInfrastructureFaults(List<FaultContractInfo> faultContractInfos)
- {
- faultContractInfos.Add(new FaultContractInfo(FaultCodeConstants.Actions.NetDispatcher, typeof(ExceptionDetail)));
- }
- static MessageFault CreateMessageFault(XmlObjectSerializer serializer, FaultException faultException, Type detailType)
- {
- if (detailType == null)
- {
- if (faultException.Fault != null)
- return faultException.Fault;
- return MessageFault.CreateFault(faultException.Code, faultException.Reason);
- }
- Fx.Assert(serializer != null, "");
- Type operationFaultType = typeof(OperationFault<>).MakeGenericType(detailType);
- return (MessageFault)Activator.CreateInstance(operationFaultType, serializer, faultException);
- }
- internal class OperationFault<T> : XmlObjectSerializerFault
- {
- public OperationFault(XmlObjectSerializer serializer, FaultException<T> faultException) :
- base(faultException.Code, faultException.Reason,
- faultException.Detail,
- serializer,
- string.Empty/*actor*/,
- string.Empty/*node*/)
- {
- }
- }
- }
- }
|