类方法WCF学习笔记-KnowTypeAttribute用法
最近研究类方法,稍微总结一下,以后继续补充:
版权所有,转载请注明出处:http://guangboo.org/2013/05/23/wcf-knowtypeattribute
C#开发语言中有类的继承,当类的继承出现在WCF的DataContract中时,就需要特殊处理,例如:
[DataContract] class Customer : Contact { ... }
服务左券的定义如下:
[ServiceContract] interface IContactManager { [OperationContract] void AddContact(Contact contact); [OperationContract] Contact[] GetContacts(); }
当我们在WCF客户端编写如下代码时,虽然代码可以编译,但是在运行时却会报错:
ContactManagerClient client = new ContactManagerClient(); Contact contact = new Customer(); client.AddContact(contact); // will fail.
原因就是WCF在对contact参数停止反序列化时,不知道它是Customer类,同样,当服务左券在实现GetContacts方法时,如果外部返回的是Customer[]的话,客户端也没法反序列化。
KnowTypeAttribute属性
WCF供给了KnowTypeAttribute属性,用于标识类或结构体,拥有的子类,是不是方法如:
[DataContract] [KnowType(typeof(Customer))] class Contact { ... }
需要注意的时,KnowTypeAttribute是使用在基类上,如果基类有多个子类,那么就需要在基类中都标记出来,而子类的定义没有变化。
ServiceKnowTypeAttribute属性
WCF还供给了ServiceKnowTypeAttribute属性,该属性也可以到达下面KnowTypeAttribute的目标,只是用法有些不同。ServiceKnowTypeAttribute属性用于标记在接口,方法,类上。其使用方法如下:
[DataContract] class Contact { ... } [DataContract] class Customer : Contact { ... } [ServiceContract] interface IContactManager { [OperationContract] [ServiceKnowType(typeof(Customer))] void AddContact(Contact contact); [OperationContract] Contact[] GetContacts(); }
下面的代码ServiceKnowTypeAttribute用于方法AddContact,那么当客户端调用该方法时,传递Customer对象时,服务端可以成功反序列化contact参数,然后没有标记的GetContacts方法,则不会其作用,如果客户端调用该方法的话,依然会没法反序列化。但是ServiceKnowType可以标记接口,那么,接口的定义如下时,则所有方法都可以畸形调用:
[ServiceContract] [ServiceKnowType(typeof(Customer))] interface IContactManager { [OperationContract] void AddContact(Contact contact); [OperationContract] Contact[] GetContacts(); }
但是需要注意的是ServiceKnowTypeAttribute虽然可以标记在类上,但是只要当该类作为服务左券,而没有实现任何服务左券接口时,可以使用(当然我们建议将左券定义在接口是好的习惯)。但是如果有左券接口,依然将ServiceKnowTypeAttribute定义在类上,那么就不会起作用。
无论是使用KonwTypeAttribute还是ServiceKonwTypeAttribute,导出的代理类都将使用前者来标记。也就是说,即使我们使用ServiceKnowTypeAttribute标记在服务左券接口上,而数据左券Contact及服务左券的方法都没有标记KnowTypeAttribute或ServiceKnowTypeAttribute,但导出的代理类都市使用。
KnowTypeAttribute标记Contact上。如服务端定义:
[ServiceContract] [ServiceKnowType(typeof(Customer))] interface IContactManager { ... }
那么导出的代理类都是如下定义:
[DataContract] [KnowType(typeof(Customer))] class Contact { ... } [DataContract] class Customer : Contact { ... } [ServiceContract] interface IContactManager { ... }
当然如果你不是通过导出代理类的方式来使用WCF服务,而是直接使用数据左券和服务左券的定义的话,也是可以的。通常建议这么做。
[DataContract] class Customer : Contact { ... } [DataContract] class Person : Customer { ... }
[ServiceContract] [ServiceKnowType(typeof(Customer))] [ServiceKnowType(typeof(Person))] interface IContactManager { ... }
配置Konw Types
<system.runtime.serialization> <dataContractSerializer> <declaredTypes> <add type="Contracts.Contact, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <knownType type="Contracts.Customer, Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> </add> </declaredTypes> </dataContractSerializer> </system.runtime.serialization>
文章结束给大家分享下程序员的一些笑话语录: 马云喜欢把自己包装成教主,张朝阳喜欢把自己包装成明星,李彦宏喜欢把自己包装成的很知性,丁磊喜欢把自己包装的有创意,李开复总摆出一副叫兽的样子。看来的。其实我想说,缺啥补啥,人之常情。
---------------------------------
原创文章 By
类和方法
---------------------------------