迁移WCF至.NET Standard 2.0:DataContractSerializerOperationBehavior代理配置问题
解决方案:在.NET Standard 2.0中为DataContractSerializerOperationBehavior注入自定义Surrogate
我之前在迁移WCF代码到.NET Standard 2.0并使用System.ServiceModel.Primitives 4.5.0-preview1版本时,也碰到了一模一样的问题——原来的DataContractSerializerOperationBehavior.DataContractSurrogate属性确实被移除了。不过通过自定义操作行为替换序列化器工厂的方式,完全可以实现注入自定义ISerializationSurrogateProvider的需求,下面是具体的实现步骤:
1. 创建自定义操作行为和序列化器工厂
我们需要实现一个IOperationBehavior,用来替换默认的DataContractSerializerFactory,让它在创建DataContractSerializer时带上我们的代理类:
// 自定义操作行为,用于注入Surrogate public class SurrogateOperationBehavior : IOperationBehavior { private readonly ISerializationSurrogateProvider _surrogate; public SurrogateOperationBehavior(ISerializationSurrogateProvider surrogate) { _surrogate = surrogate; } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { // 无需额外处理 } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { ReplaceDefaultSerializer(operationDescription); } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { ReplaceDefaultSerializer(operationDescription); } public void Validate(OperationDescription operationDescription) { // 无需额外处理 } private void ReplaceDefaultSerializer(OperationDescription operationDescription) { // 找到当前操作上的DataContractSerializerOperationBehavior var dcsBehavior = operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>(); if (dcsBehavior != null) { // 替换为我们自定义的序列化器工厂 dcsBehavior.SerializerFactory = new SurrogateSerializerFactory(_surrogate); } } } // 自定义序列化器工厂,创建带有Surrogate的DataContractSerializer public class SurrogateSerializerFactory : DataContractSerializerFactory { private readonly ISerializationSurrogateProvider _surrogate; public SurrogateSerializerFactory(ISerializationSurrogateProvider surrogate) { _surrogate = surrogate; } public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes) { var settings = new DataContractSerializerSettings { DataContractSurrogate = _surrogate, KnownTypes = knownTypes }; return new DataContractSerializer(type, name, ns, settings); } public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes) { var settings = new DataContractSerializerSettings { DataContractSurrogate = _surrogate, KnownTypes = knownTypes }; return new DataContractSerializer(type, name, ns, settings); } }
2. 将自定义行为添加到服务或客户端
服务端配置
在创建ServiceHost后,遍历所有端点和操作,添加我们的自定义行为:
var serviceHost = new ServiceHost(typeof(MyService)); // 遍历所有端点 foreach (var endpoint in serviceHost.Description.Endpoints) { // 遍历端点下的所有操作 foreach (var operation in endpoint.Contract.Operations) { operation.Behaviors.Add(new SurrogateOperationBehavior(new MyDataContractSurrogate())); } } serviceHost.Open();
客户端配置
在创建ChannelFactory后,同样遍历操作添加行为:
var binding = new BasicHttpBinding(); var endpointAddress = new EndpointAddress("http://localhost/MyService"); var factory = new ChannelFactory<IMyService>(binding, endpointAddress); foreach (var operation in factory.Endpoint.Contract.Operations) { operation.Behaviors.Add(new SurrogateOperationBehavior(new MyDataContractSurrogate())); } var channel = factory.CreateChannel(); // 开始使用channel调用服务
关键说明
- 核心思路是替换默认的
SerializerFactory,让它在实例化DataContractSerializer时,通过DataContractSerializerSettings注入你的MyDataContractSurrogate。 - 确保你的
MyDataContractSurrogate正确实现了ISerializationSurrogateProvider的所有方法:GetDeserializedObject、GetObjectToSerialize、GetKnownCustomDataTypes和GetSurrogateType。
内容的提问来源于stack exchange,提问作者HPaxton
相关产品推荐
相关产品推荐

