版权所有,转载请注明出处: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 { ... }
即使服务实现里只用到Person类,也要将Customer标记进去。即:
[ServiceContract]
[ServiceKnowType(typeof(Customer))]
[ServiceKnowType(typeof(Person))]
interface IContactManager { ... }
配置Konw Types
WCF提供了强大的配置功能,以上方法都能解决子类DataContract问题,但是每添加一个子类都要在ServiceContract接口上添加ServiceKnowTypeAttribute来标记子类。其实WCF也针对KnowType提供了配置实现。需要注意的是,需要配置类名和程序集全名。如下示例:
<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>
分享到:
相关推荐
WCF简单实例--WCF简单实例--WCF简单实例--WCF简单实例--WCF简单实例--WCF简单实例--
WCF入门指导 引你进入WCF的大门 WCF、WCF
WCF学习笔记 WCF学习笔记 WCF学习笔记 WCF学习笔记 WCF学习笔记 WCF学习笔记
(英文版)WCF 4.0 Multi-tier Services Development with LINQ to Entities Packt Publishing 出版2010, PDF格式
WCF学习笔记, 一步一步教你学习WCF
WCF学习笔记 WCF学习笔记 WCF学习笔记
WCF代码1-简单的WCF程序WCF代码1-简单的WCF程序
(2):WCF契约设计-WCF课件-《构建WCF面向服务的应用程序》
WCF 4.0 Multi-tier Services Development.with LINQ to Entities
WCF 4.5 Multi-Layer Services WCF C# .net webservice soap
WCF 4.5 Multi-Layer Services Development with Entity Framework(3rd) 英文无水印pdf 第3版 pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn...
学习.net wcf 入门版 pdf english
实践WCF中的MessageContract与IXmlSerializable
WCF 学习笔记 WCF 杂项 WCF Security WCF Transaction WCF MSMQ __
WCF 实例源代码------聊天室 WCF 实例源代码------聊天室
教你轻松掌握WCF基础知识,详细描述WCF基本原理及实例讲解
WCF学习的相关资料,这些都是我从网上收集整理的,想学习的人有福啦
这是一个Ext框架,我对此框架很感兴趣。。。特别想了解一下。。。
WCF部署在IIS上,使用net.tcp比较简单详细的配置
WCF学习笔记,自己整理,xps格式。内容详实,清晰,带有代码,方便调试。