using System; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; namespace Asb.Base.V2.Serialization; public sealed class BaseV2SerializerContractBehaviorAttribute : Attribute, IContractBehavior { public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { ReplaceSerializerOperationBehavior(contractDescription); } public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { ReplaceSerializerOperationBehavior(contractDescription); } public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { 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); } } } } private static void ValidateMessagePartDescription(MessagePartDescription part) { if (part != null) { ValidateCustomSerializableType(part.Type); } } private static void ValidateCustomSerializableType(Type type) { if (typeof(IBaseV2CustomSerializable).IsAssignableFrom(type)) { if (!type.IsPublic) { throw new InvalidOperationException("Custom serialization is supported in public types only"); } if (type.IsClass && type.GetConstructor(new Type[0]) == null) { throw new InvalidOperationException("Custom serializable types must have a public, parameterless constructor"); } } } private static void ReplaceSerializerOperationBehavior(ContractDescription contract) { foreach (OperationDescription operation in contract.Operations) { for (int i = 0; i < operation.Behaviors.Count; i++) { if (operation.Behaviors[i] is DataContractSerializerOperationBehavior) { operation.Behaviors[i] = new BaseV2SerializerOperationBehavior(operation); } } } } }