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文章数据协定继承,这里就不多介绍了


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM