WCF入门(三)——对象序列化

对象序列化

WCF是通过网络实现远程方法调用的,因此参数,返回值等都需要序列化才能在网络间传输。例如,对于下面的一个服务:

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        Point GetRandomPoint();
    }

    public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
    }

    public class Service1 : IService1
    {
        public Point GetRandomPoint()
        {
            var rnd = new Random();
            return new Point() { X = rnd.Next(), Y = rnd.Next() };
        }
    }

可以通过WCF测试客户端查看其数据是如何传输的。

从中我们可以看到,对于返回值Point,是将其序列化成了Xml格式后传递的,在WCF中,默认是通过DataContractSerializer序列化对象的,它可以将对象序列化成XML,我们也可以手动编码实现这一过程。

    var point = new Point(){X = 1,Y = 2};
    var serializer = new DataContractSerializer(typeof(Point));
    serializer.WriteObject(stream, point);

序列化控制

从前面的例子可以看到,即使什么都不干,只要定义了一个对象,DataContractSerializer就能将其序列化。但这个默认的序列化方式是直接根据字段名称来序列化的,很多时候,为了实现更好的版本控制,往往需要我们控制序列化格式。

一个简单的示例如下:

    [DataContract]
    public class Point
    {
        [DataMember(Name="PointX")] public int X { get; set; }
        [DataMember(Name="PointY")] public int Y { get; set; }
    }

实现这个序列化控制后,执行结果为:

从这个例子中可以看到,和传统的XmlSerializer一样,WCF是通过一些Attribute进行序列化控制的,基本方式为:

  1. 通过 DataContract 标志要序列化的对象
  2. 通过 DataMember 标志序列化成员,并通过参数控制序列化过程。

当然,其序列化控制手段远远不止这么点,更多信息可以参看MSDN:创建类或结构的基本数据协定

将对象序列化成Json格式

XML虽然具有良好的可读性,但开销非常大,增大了网络传输负担,对于那些网速不够快的场景则需要开销更小的序列化格式,一种比较常用的开销更小的序列化格式就是Json。

WCF是一个通用的网络传输平台,在WCF中,可以借助DataContractJsonSerializer实现序列化对象为Json格式。例如,对于前面的那个Point结构,可以序列化为如下形式:

    {"PointX":1,"PointY":2}

可以看到,DataContract的序列化控制对DataContractJsonSerializer也是生效的,这说明DataContract是一个通用的序列化控制手段,这也是它们叫DataMember这类比较抽象的名字,而不是叫XmlElement之类的具体名字的原因。

要把WCF服务配置成以Json方式传输数据格式,可以参考这篇文章Using WebHttpBinding & JSON Support in WCF

注意事项

在WCF传输数据时,注意返回的对象类型不能是返回值类型的子类(Stream除外)。拿前面的例子来说,修改代码为:返回一个Point的子类Point3D对象。

    public class Point3D : Point
    {
        public int Z { get; set; }
    }


    public class Service1 : IService1
    {
        public
PointGetRandomPoint()
        {
            var rnd = new Random();
            return new
Point3D() { X = rnd.Next(), Y = rnd.Next() };
        }
    }

这个时候是完全能通过编译并运行的,但是调用函数的时候就会出现如下错误:

这个主要还是传输的数据格式不匹配造成的,WCF中可以使用KnownTypeAttribute标记解决这一问题,具体可以参看MSDN文章数据协定继承,这里就不多介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值