WCF DataContract標記去除方式解析
WCF是一個基于.Net Framework 2.0基礎的由微軟公司研發的開發插件,它的實際應用可以幫助編程人員輕松實現特定的功能需求。在這里我們將會介紹一種應用技巧,就是如何在使用中省略掉WCF DataContract標記。#t#
寫過WCF程序的朋友都知道,在對實體對象在WCF和客戶端之間傳遞時一定要加WCF DataContract標記這個類并用DataMember來標記要序列化的屬性/字段。這一直正確,只是在.NET Framework 3.5 SP1中新添加了一些支持,那就是你不一定必須對這些實體對象應用DataContract標記,這被稱作對plain old C# objects(POCO)的序列化支持。
Serializable標記大家都很熟悉,它是XmlSerializer的標記,在WCF中其實很少用這個標記,因為我們WCF用的是DataContractSerializer,對應的標記也是DataContract。但對于SP1來說,Serializable也以XmlSerializer的規則被正常解析,其對應的Mapping規則和Serializer對應,其公有可讀寫字段被默認序列化。當然,你也可以通過XmlElement等標記來做高級映射,但這不是我們這里需要談及的內容。
WCF DataContract標記對應的序列化處理叫做DataContactSerializer。在WCF中一旦一個類被標記為DataContract,那么只有標記為DataMember的字段/屬性才會被序列化。但如果你使用DataContract標記,那么DataContractSerializer默認將所有公有可讀寫字段序列化(這和Serializable是一樣的)。假設我們有這么一個類:
- public class Person
- {
- public Person()
- { }
- public Person(string strId, string strName)
- {
- this.Id = strId;
- this.Name = strName;
- }
- private string strid;
- public string Id { get { return strid; } set { strid = value; } }
- public string Name;
- public Person Spouse;
- private int Number = 343;
- }
對于DataSerializer來說,他和給所有公有屬性添加DataMember并將類標記為WCF DataContract標記是一樣的。下面的一段程序分別將一個Person的實例對象分別用XmlSerializer和DataContractSerializer來序列化:
- static void Main(string[] args)
- {
- Person p = new Person();
- p.Id = "123";
- p.Name = "Aaron";
- p.Spouse = new Person();
- p.Spouse.Id = "456";
- p.Spouse.Name = "Monica";
- DataContractSerializer dcs = new
DataContractSerializer(typeof(Person));- using (FileStream fs = new FileStream("person.xml",
FileMode.Create))- {
- dcs.WriteObject(fs, p);
- }
- XmlSerializer xs = new XmlSerializer(typeof(Person));
- using (FileStream fs = new FileStream("person_serialization.xml",
FileMode.Create))- {
- xs.Serialize(fs, p);
- }
- }
對于序列化后的內容我們得到的結果其實是一樣的:僅有公有屬性/字段被序列化
- < Person xmlns="http://schemas.datacontract.org/2004/07/
Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">- < Id>123< /Id>
- < Name>Aaron< /Name>
- < Spouse>
- < Id>456< /Id>
- < Name>Monica< /Name>
- < Spouse i:nil="true"/>
- < /Spouse>
- < /Person>
但如果你使用了DataContract來標記這個類,卻沒有使用DataMember,那么沒有任何屬性/字段被序列化:
- [DataContract]
- public class Person
- {
- private string strid;
- public string Id { get { return strid; } set { strid = value; } }
- public string Name;
- public Person Spouse;
- private int Number = 343;
- }
- < Person xmlns="http://schemas.datacontract.org/2004/07/
Serialization" xmlns:i=http://www.w3.org/2001/XMLSchema-instance />
對于將類標記成Serializable,DataContractSerializer的序列化可能讓我們覺得有些奇怪,它本質上是將所有可讀寫字段序列化,這其中還包括私有字段。例如我們將Person類用[Serializable]標記,執行程序,我們會得到以下的結果:
- < Person xmlns="http://schemas.datacontract.org/2004/07
/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">- < Name>Aaron< /Name>
- < Number>0< /Number>
- < Spouse>
- < Name>Monica< /Name>
- < Number>0< /Number>
- < Spouse i:nil="true"/>
- < _id>456< /_id>
- < /Spouse>
- < _id>123< /_id>
- < /Person>
一個簡單的WCF程序來看看來檢驗一下是否正確。在Contract生命中我們并不需要制定任何的標記,并聲明一個得到DeskMesh的方法:
- [ServiceContract]
- public interface IDeskMesh
- {
- [OperationContract]
- DeskMesh GetDeskMesh(string name);
- }
- public class DeskMesh
- {
- private int _id;
- private int Number = 4433;
- public int ID
- {
- get { return _id; }
- set { _id = value; }
- }
- public string Name { get; set; }
- public string Description { get; set; }
- public string Unit { get; set; }
- public float Price { get; set; }
- public DateTime Created { get; set; }
- public override string ToString()
- {
- return string.Format("ID:{4}"r"nName: {0}"r"nUnit:{1}"r"
nPrice:{2}"r"nCreated:{3}"r"nNumber:{5}",- Name, Unit, Price, Created.ToShortDateString(),
ID.ToString(),Number.ToString());- }
- }
客戶端調用,會返回一個DeskMesh的實例。通過結果,你會發現這完全和你標記WCF DataContract標記的實體在WCF兩端傳遞一模一樣。
- void Main(string[] args)
- {
- Console.WriteLine("Requesting...");
- ServiceClient client = new ServiceClient();
- DeskMesh mesh = client.GetDeskMesh("");
- Console.WriteLine(mesh.ToString());
- Console.WriteLine("press any key to continue...");
- Console.Read();
- }
總結一下吧,WCF中應用各個標記時所作的序列化處理:
1. 不給任何標記將會做XML映射,所有公有屬性/字段都會被序列化
2. [Serializable]標記會將所有可讀寫字段序列化
3. [DataContract]和[DataMember]聯合使用來標記被序列化的字段
以上就是對WCF DataContract標記的相關介紹。