WCF接口、抽象类等数据契约传递方式
来源:互联网 发布:湄公河大案泰国 知乎 编辑:程序博客网 时间:2024/04/30 12:00
WCF中传输的数据不像传统的面向对象编程,它只传递了一些对象的属性,但是自身并不知道自己属于什么对象,所以,他没有子类和父类的概念,因而也就没有Is-a的关系,所以在WCF中,如果想维持这种继承关系,就需要做一些特殊的处理了。
假设有如下定义
namespace KnownTypeExampleInterface{ [DataContract] public class Employee { [DataMember] public string Name { get; set; } [DataMember] public string Age { get; set; } } [DataContract] public class Manager:Employee { [DataMember] public int OfficeId { get; set; } } public interface IHumanResourceService { List<Employee> GetAllEmployees(); }}
这样,在调用端是无法得到manager的OfficeId的,因为在服务定义中并不知道有Manager类的存在,而且会有错误提示。
解决这种问题的有如下几种方法
代码中定义
解决这种问题的一种方法是使用KnownTypeAttribute告诉WCF存在Manager的信息:
[DataContract][KnownType(typeof(Manager))]public class Employee{ [DataMember] public string Name { get; set; } [DataMember] public string Age { get; set; }}
配置中定义
在代码中定义的有一个主要的缺陷,就是客户端必须事先知道这些子类,添加一个子类就得修改一次代码,重新编译,部署,所以WCF也允许允许通过配置文件的方式添加这些子类。
<system.runtime.serialization> <dataContractSerializer> <declaredTypes> <add type="Employee,KnownTypeExampleInterface,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"> <knownType type="Manager,KnownTypeExampleInterface,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/> </add> </declaredTypes> </dataContractSerializer> </system.runtime.serialization>
宿主端使用解析器
另外一种清大的方法就是使用数据契约解析器,它能够自动化的去解析这些子类,而不需要手动的去添加标签或者修改配置文件。
实现这种数据契约解析器的方法
在WCF中,存在DataContractResolver类,可以在这个类中提供一个维护了唯一标识符和类型之间的映射关系字典,在序列化这个类型时,需要提供一个唯一的标识符作为键形成键与类型的映射关系,WCF会在反序列化期间提供这些键。参照上文中的数据契约,相对应的解析器定义为:
public abstract class ManagerDataContractResolver:DataContractResolver{ private string Namespace { get { return typeof (Manager).Namespace ?? "global"; } } private string Name { get { return typeof (Manager).Name; } } public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) { if (typeName == this.Name && typeNamespace == this.Namespace) { return typeof (Manager); } else { return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); } } public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) { if (type == typeof (Manager)) { XmlDictionary dic = new XmlDictionary(); typeName = dic.Add(this.Name); typeNamespace = dic.Add(this.Namespace); return true; } else { return knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace); } }}
自定义的解析器定义完成,之后需要分别在代理端和宿主端安装解析器,
在ServiceEndpoint中有一个类型为ContractDascription的Contract属性,它是一个操作描述的集合,每一个描述操作描述(OperationDescription)都包含一个类型为IOperationBehavior类型的行为集合,而每一个行为又包含一个DataContractResolver属性,这个属性默认为null,就是在这里,可以设置我们自定义的解析器。
static void Main(string[] args){ ServiceHost host = new ServiceHost(typeof (HumanResourceService)); foreach (ServiceEndpoint endpoint in host.Description.Endpoints) { foreach (OperationDescription operation in endpoint.Contract.Operations) { DataContractSerializerOperationBehavior behavior = operation.OperationBehaviors.FirstOrDefault( x => x.GetType() == typeof (DataContractSerializerOperationBehavior)) as DataContractSerializerOperationBehavior; behavior.DataContractResolver = new ManagerDataContractResolver(); } } host.Open(); Console.WriteLine("Host Running!"); Console.ReadKey(); host.Close();}
- WCF接口、抽象类等数据契约传递方式
- wcf接口契约
- wcf数据契约
- WCF 数据契约
- 进一步学习WCF:数据契约,序列化等
- WCF契约设计: 服务契约,数据契约和消息契约
- WCF契约之---服务契约 、数据契约、 消息契约
- WCF中接口与WCF契约
- WCF数据契约(DataContract)
- WCF定义数据契约注意事项
- 谈WCF数据契约疑问之共享数据契约
- WCF学习笔记(二)使用Name等属性和数据契约
- WCF契约的简单介绍(服务契约 数据契约 消息契约)
- WCF契约的简单介绍(服务契约 数据契约 消息契约)
- WCF契约的简介(服务契约、数据契约和消息契约)
- WCF契约的简单介绍(服务契约 数据契约 消息契约)
- WCF流与文件传输、数据契约和消息契约
- WCF编码规范(四)数据契约
- 大话商学院(1)--卖iPad给小孩一定要从父母的教育账户里掏钱
- python中pandas包学习笔记(1)
- Pinctrl-bindings.txt
- 基于《机器学习》学习整理- chapter 1
- Spring Boot+Maven 工程配置h2内存数据库
- WCF接口、抽象类等数据契约传递方式
- Linux常用搜索命令grep命令
- mysql 5.7.13 安装配置方法图文教程(linux)
- 如何将逻辑中后面算出的数据提前输出-- 计数的范围素数
- 正则化的意义
- java script 初识
- JVM 垃圾回收器工作原理及使用实例介绍
- 百度语音识别,显示权限不够的问题
- 深度学习框架Caffe学习笔记(6)-测试自己的手写数字图片