已知类型(Known types)允许在服务契约中使用多态的行为,在服务操作中暴露基本类型。
将已知类型(known types)相关到基本类型(基类类型)自身;特定操作;整个服务契约
采用属性声明或者配置的方式来实现
1、[KnownType]: 相关到基本类型(基类类型)自身
[DataContract(Namespace ="htttp://www.cnblogs.com/Charlesliu")] [KnownType(typeof(GigInfo))] [KnownType(typeof(PhotoLink))] [KnownType(typeof(MP3Link))] public class LinkItem [DataContract(Namespace ="htttp://www.cnblogs.com/Charlesliu")] public class GigInfo: LinkItem [DataContract(Namespace ="htttp://www.cnblogs.com/Charlesliu")] public class PhotoLink: LinkItem [DataContract(Namespace ="htttp://www.cnblogs.com/Charlesliu")] public class MP3Link: LinkItem
2、[ServiceKnownType]: 相关到整个服务契约
[ServiceContract(Name = "GigManagerContract", Namespace ="http://www.cnblogs.com/Charlesliu")] [ServiceKnownType(typeof(GigInfo))] [ServiceKnownType(typeof(PhotoLink))] [ServiceKnownType(typeof(MP3Link))] public interface IGigManagerService { [OperationContract] void SaveLink(LinkItem item); [OperationContract] LinkItem GetLink(string id); }
3、[ServiceKnownType]: 相关到特定操作
[ServiceContract(Name = "GigManagerContract", Namespace ="http://www.cnblogs.com/Charlesliu")] public interface IGigManagerService { [OperationContract] [ServiceKnownType(typeof(GigInfo))] void SaveGig(LinkItem item); [OperationContract] [ServiceKnownType(typeof(GigInfo))] LinkItem GetGig(string id); }
下面看一个具体的Demo,然后根据代码讲解:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; namespace ContentTypes { [DataContract(Namespace = "http://www.cnblogs.com/Charlesliu")] public enum LinkItemCategories { [EnumMember] Gig, [EnumMember] MP3, [EnumMember] Photo } [DataContract(Name = "LinkItem_Contract", Namespace = "http://www.cnblogs.com/Charlesliu")] [KnownType(typeof(GigInfo))] [KnownType(typeof(PhotoLink))] [KnownType(typeof(MP3Link))] public class LinkItem { private long m_id; private string m_title; private string m_description; private DateTime m_dateStart; private DateTime m_dateEnd; private string m_url; private LinkItemCategories m_category; [DataMember(Name = "Id_Contract", IsRequired = false, Order = 0)] public long Id { get { return m_id; } set { m_id = value; } } [DataMember(Name = "Title_Contract", IsRequired = true, Order = 1)] public string Title { get { return m_title; } set { m_title = value; } } [DataMember(Name = "Description_Contract", IsRequired = true, Order = 2)] public string Description { get { return m_description; } set { m_description = value; } } [DataMember(Name = "DateStart_Contract", IsRequired = true, Order = 3)] public DateTime DateStart { get { return m_dateStart; } set { m_dateStart = value; } } [DataMember(Name = "DateEnd_Contract", IsRequired = false, Order = 4)] public DateTime DateEnd { get { return m_dateEnd; } set { m_dateEnd = value; } } [DataMember(Name = "Url_Contract", IsRequired = false, Order = 5)] public string Url { get { return m_url; } set { m_url = value; } } [DataMember(Name = "Category_Contract", IsRequired = false, Order = 6)] public LinkItemCategories Category { get { return m_category; } set { m_category = value; } } } [DataContract(Namespace = "http://www.cnblogs.com/Charlesliu")] public class GigInfo : LinkItem { public GigInfo() { this.Category = LinkItemCategories.Gig; } } [DataContract(Namespace = "http://www.cnblogs.com/Charlesliu")] public class MP3Link : LinkItem { public MP3Link() { this.Category = LinkItemCategories.MP3; } } [DataContract(Namespace = "http://www.cnblogs.com/Charlesliu")] public class PhotoLink : LinkItem { public PhotoLink() { this.Category = LinkItemCategories.Photo; } } }
enum类型可以用[EnumMember]标记,本例中如果不加[KnownType]的相关标记,那么在客户端是看不到子类型的。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using ContentTypes; namespace WcfServiceLibraryDemo { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class GigManagerService : IGigManagerService {
private LinkItem m_linkItem; #region IGigManager Members public void SaveGig(LinkItem item) { m_linkItem = item; } public LinkItem GetGig() { return m_linkItem; } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using ContentTypes; namespace WcfServiceLibraryDemo { [ServiceContract(Name = "GigManagerServiceContract", Namespace = "http://www.cnblogs.com/Charlesliu", SessionMode = SessionMode.Required)] public interface IGigManagerService { [OperationContract(Name = "SaveGig", Action = "http://www.cnblogs.com/Charlesliu/GigManagerServiceContract/SaveGig",
ReplyAction = "http://www.cnblogs.com/Charlesliu/GigManagerServiceContract/SaveGigResponse")] void SaveGig(LinkItem item); [OperationContract(Name = "GetGig", Action = "http://www.cnblogs.com/Charlesliu/GigManagerServiceContract/GetGig",
ReplyAction = "http://www.cnblogs.com/Charlesliu/GigManagerServiceContract/GetGigResponse")] LinkItem GetGig(); } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using WinTest.MyServiceReference; namespace WinTest { public partial class Form1 : Form { MyServiceReference.GigManagerServiceContractClient m_proxy = new WinTest.MyServiceReference.GigManagerServiceContractClient(); public Form1() { InitializeComponent(); } private void cmdSave_Click(object sender, EventArgs e) { MP3Link item = new MP3Link(); item.Id_Contract = int.Parse(this.txtId.Text); item.Title_Contract = this.txtTitle.Text; item.Description_Contract = this.txtDescription.Text; item.DateStart_Contract = this.dtpStart.Value; item.DateEnd_Contract = this.dtpEnd.Value; item.Url_Contract = this.txtUrl.Text; m_proxy.SaveGig(item); } private void cmdGet_Click(object sender, EventArgs e) { MP3Link item = (MP3Link)m_proxy.GetGig(); if (item != null) { this.txtId.Text = item.Id_Contract.ToString(); this.txtTitle.Text = item.Title_Contract; this.txtDescription.Text = item.Description_Contract; if (item.DateStart_Contract != DateTime.MinValue) this.dtpStart.Value = item.DateStart_Contract; if (item.DateEnd_Contract != DateTime.MinValue) this.dtpEnd.Value = item.DateEnd_Contract; this.txtUrl.Text = item.Url_Contract; } } } }
客户端用的是MP3Link这个类,通过[KnownType]实现了WCF的多态。