#define TRACE using System; using System.Diagnostics; using System.Globalization; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using ArchestrAServices.Common; namespace ArchestrAServices.Contract; public class ASBCustomSerializerContractBehavior : IContractBehavior { public virtual void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public virtual void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { ReplaceSerializerOperationBehavior(contractDescription); } public virtual void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { ReplaceSerializerOperationBehavior(contractDescription); } public virtual void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { if (contractDescription == null) { return; } foreach (OperationDescription operation in contractDescription.Operations) { foreach (MessageDescription message in operation.Messages) { ValidateMessagePartDescription(message.Body.ReturnValue); foreach (MessagePartDescription part in message.Body.Parts) { ValidateMessagePartDescription(part); } foreach (MessageHeaderDescription header in message.Headers) { ValidateCustomSerializableType(header.Type); } } } } protected virtual void ValidateMessagePartDescription(MessagePartDescription part) { if (part != null) { ValidateCustomSerializableType(part.Type); } } protected virtual void ValidateCustomSerializableType(Type type) { Type type2 = type; if (null != type && type.IsArray) { type2 = type.GetElementType(); } if (typeof(IASBCustomSerializableType).IsAssignableFrom(type2)) { if (!type2.IsPublic) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, string.Format(CultureInfo.CurrentCulture, "ASBCustomSerializerContractBehaviorAttribute:ValidateCustomSerializableType- Custom serialization is supported in public types only")); } if (type2.IsClass && type2.GetConstructor(new Type[0]) == null) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Warning, 0, string.Format(CultureInfo.CurrentCulture, "ASBCustomSerializerContractBehaviorAttribute:ValidateCustomSerializableType- Custom serializable types must have a public, parameterless constructor")); } } } protected virtual void ReplaceSerializerOperationBehavior(ContractDescription contract) { if (contract == null) { return; } foreach (OperationDescription operation in contract.Operations) { for (int i = 0; i < operation.Behaviors.Count; i++) { if (operation.Behaviors[i] is DataContractSerializerOperationBehavior) { if (typeof(DataContractSerializerOperationBehavior).IsAssignableFrom(typeof(T))) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, string.Format(CultureInfo.CurrentCulture, "Replacing the default serialization with ASB-Specific custom serialization")); operation.Behaviors[i] = Activator.CreateInstance(typeof(T), operation) as DataContractSerializerOperationBehavior; } else { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Warning, 0, string.Format(CultureInfo.CurrentCulture, "ASBCustomSerializerOperationBehavior:CreateSerializer-failed to create instance for DataContractSerializerOperationBehavior. Invalid type {0}", new object[1] { typeof(T).FullName })); } } } } } }