这一节探讨下关于数据契约继承的问题,关于数据契约的继承,主要包括以下几个方面
1.数据契约继承
2.KnowType的使用
3.ServiceKnownType的使用
接下下来我们一一了解
1.数据契约的继承
一个被声明为数据契约的类型,可以被另一个数据契约继承。子类的数据契约包含继承父类的所有数据契约。
/// <summary>
/// 水果
/// </summary>
[DataContract]
public class Fruits
{
/// <summary>
/// 名称
/// </summary>
[DataMember(IsRequired = true, Order = 0)]
public string Name
{
get;
set;
}
/// <summary>
/// 颜色
/// </summary>
[DataMember(IsRequired = true, Order = 1)]
public string Color
{
get;
set;
}
/// <summary>
/// 形状
/// </summary>
public string Shape
{
get;
set;
}
}
[DataContract]
public class Apple:Fruits
{
/// <summary>
/// 描述信息
/// </summary>
[DataMember]
public string Des
{
get;
set;
}
}
上面的代码中,Apple契约继承了Fruits契约,也就是说Fruits契约里面的所有属性,在APPLE契约里面都可以使用。
IsRequired属性表示当服务器端契约添加了新的属性,客户端没有更新契约版本的时候,如果IsRequired=true,就会报错,TRUE代表在通信过程中,此属性一定要被序列化才能进行通信,如果为FALSE,通信过程中不需要对此属性进行序列化,默认值为属性所在类型的默认值,字符串为空,整形为0.
Order表示在序列化后,源数据在XSD文件中的排列顺序,值越小,在XSD文件中位置越靠前。
接下来我们采用如下方式调用契约
[ServiceContract]
public interface IDataService
{
[OperationContract]
Fruits GetFruits(Apple app);
}
public class DataService : IDataService
{
#region IDataService 成员
public Fruits GetFruits(Apple app)
{
app.Name = app.Name + "one";
app.Des = "收到IPHONE";
return app;
}
#endregion
}
以上方法在编译的时候一切运行正常,但是如果客户端调用的时候,就会抛出异常,原因契约是面向服务的,不能像面向对象语言那样,直接可以将子类转换为父类。
如果需要在WCF中,可以将子类契约转换为父类契约,需要使用KnownType.
2.KnownType用法
在面向对象的语言中,可以使用多态,将子类转换为父类,但是WCF属于面向服务的设计架构,牺牲了面向对象的一些优点。由于客户端和服务端进行通信的时候,要进行
一系列的序列化和反序列化,所以不能使用多态,但是我们可以通过另一种方式来实现。使用KnownType标记继承当前类的所有子类,这样在使用的时候就可以使用多态
[KnownType(typeof(Apple))],也就是说,如果一个类被多个类继承,需要提前知道继承该类的所有子类。
[KnownType(typeof(Apple))]
public class Fruits
{
/// <summary>
/// 名称
/// </summary>
[DataMember(IsRequired = true, Order = 0)]
public string Name
{
get;
set;
}
/// <summary>
/// 颜色
/// </summary>
[DataMember(IsRequired = true, Order = 1)]
public string Color
{
get;
set;
}
/// <summary>
/// 形状
/// </summary>
public string Shape
{
get;
set;
}
}
这样,我们在客户端使用的时候,就不会抛出异常了
客户端代码
private void button2_Click(object sender, EventArgs e)
{
DaService.DataServiceClient client = new DaService.DataServiceClient();
DaService.Apple app = new DaService.Apple();
app.Name = "苹果";
app.Des = "IPHONE5";
DaService.Fruits fruits=client.GetFruits(app);
MessageBox.Show(fruits.Name);
}
3.ServiceKnownType
使用ServiceKnownType可以起到与KnownType一样的作用,但ServiceKnownType需要声明在服务契约上或者服务契约特定的操作上。声明在服务契约上,说着在整个服务契约范围内都有效,声明在操作契约上,只在当前操作契约方法内有效。ServiceKnownType与KnownType两者使用其一即可.
[ServiceContract]
[ServiceKnownType(typeof(Apple))]
public interface IDataService
{
[OperationContract]
Fruits GetFruits(Apple app);
}
DEMO:http://download.csdn.net/detail/zx13525079024/4583274