在Windows Communication Foundation (WCF)中,数据契约是定义服务数据交换格式的一种方式。通常情况下,发送方和接收方都知道数据契约的类型。但在某些情况下,发送回客户端的数据并不是实际的数据契约类型,而是一个派生类型。这时,反序列化引擎将无法识别派生的数据契约类型,并会报错。为了处理这种情况,WCF提供了数据契约已知类型(Known Types)的概念。
数据契约已知类型是指在WCF中,可以接受的派生类型。在之前的WCF服务文章中,通过一个简单的例子解释了WCF的KnownTypeAttribute。但在这个WCF教程中,将尝试讨论使用数据契约已知类型所有可能的方式,以便读者能够详细了解已知类型,并能够在各种实际场景中使用它。
假设有一个服务契约“IVehicleService”,如下所示:
[ServiceContract]
public Interface IVehicleService
{
[OperationContract]
Vehicle AddNewVehicle(Vehicle myVehicle);
[OperationContract]
bool UpdateVehicle(Vehicle myVehicle);
}
可以根据需求在不同的级别使用数据契约已知类型:
使用基类型代码
使用Web.config
要全局使用,可以在基数据契约类型上应用KnownTypeAttribute,如下例所示:
[KnownType(typeof(Car))]
[KnownType(typeof(Truck))]
[DataContract]
public class Vehicle
{
}
[DataContract]
public class Car : Vehicle
{
}
[DataContract]
public class Truck : Vehicle
{
}
在上面的例子中,可以看到KnownTypeAttribute是在基数据契约类型Vehicle上使用的。因此,这些派生类型现在对所有服务和操作契约都是全局已知的,无论Vehicle类型在哪里使用。
使用Web.config也可以实现相同的效果,如下所示:
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type="MyService.Vehicle, MyService, Version=, Culture=Neutral, PublicKeyToken=null">
<knownType type="MyService.Car, MyService, Version=, Culture=Neutral, PublicKeyToken=null"/>
<knownType type="MyService.Truck, MyService, Version=, Culture=Neutral, PublicKeyToken=null"/>
</add>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
上述配置也会使派生类型(Car、Truck)成为全局已知类型。
在某些场景中,如果想要为特定服务使这些派生类型成为已知类型,可以应用ServiceKnownTypeAttribute,如下所示:
[ServiceKnownType(typeof(Car))]
[ServiceKnownType(typeof(Truck))]
[ServiceContract]
public Interface IVehicleService
{
[OperationContract]
Vehicle AddNewVehicle(Vehicle myVehicle);
[OperationContract]
bool UpdateVehicle(Vehicle myVehicle);
}
现在,这些派生类型是IVehicleService中所有操作契约的已知类型。
为了进一步限制,即只为服务中的特定操作契约,可以这样做:
[ServiceContract]
public Interface IVehicleService
{
[OperationContract]
[ServiceKnownType(typeof(Car))]
[ServiceKnownType(typeof(Truck))]
Vehicle AddNewVehicle(Vehicle myVehicle);
[OperationContract]
bool UpdateVehicle(Vehicle myVehicle);
}