那些年,我们一起学WCF--(5)数据契约继承

来源:互联网 发布:手机pdf修改软件 编辑:程序博客网 时间:2024/04/30 01:46

         这一节探讨下关于数据契约继承的问题,关于数据契约的继承,主要包括以下几个方面

             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

 


原创粉丝点击