您的位置:首页 > 其它

XmlSerializer vs DataContractSerializer: Serialization in Wcf

2008-05-04 17:06 465 查看
Ref:http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/TheXmlSerializerhasbeenin.Netsinceversion1.0andhasserveduswellforeverythingfromRemoting,WebServices,serializingtoafile,etc.Howeverin.Net3.0theDataContractSerializercamealong.AndallofasuddenalotofguidancesuggeststhatweshoulduseitovertheoldtriedandtrueXmlSerializer.Wcfevenusesthisasthedefaultmechanismforserialization.Thequestionis,“Isitreallybetter?”.Theverdictisyes,andno.Likemostthingsitdependsonyourimplementationandwhatyouneed.ForWcf,youshouldprefertousetheDataContractSerializer.Ifyouneedfullcontroloverhowthexmllooksthough,youshouldgobacktotheXmlSerializer.Letslookatthebothoftheseindetailandleaveituptoyoutodecidewhichisbestforyourimplementation.Hereareafewoftheadvantagesanddisadvantagesofeachofthem:XmlSerializer
DataContractSerializerAdvantages:
1.Opt-outratherthanopt-inpropertiestoserialize.Thismeanyoudon’thavetospecifyeachandeverypropertytoserialize,onlythoseyoudon’twantoserialize2.Fullcontroloverhowapropertyisserializedincludingititshouldbeanodeoranattribute3.SupportsmoreoftheXSDstandardDisadvantages:
1.Canonlyserializeproperties2.Propertiesmustbepublic3.Propertiesmusthaveagetandasetwhichcanresultinsomeawkwarddesign4.Supportsanarrowersetoftypes5.CannotunderstandtheDataContractAttributeandwillnotserializeitunlessthereisaSerializableAttributetooAdvantages:
1.Opt-inratherthanopt-outpropertiestoserialize.Thismeanyouspecifywhatyouwantserialize2.Becauseitisoptinyoucanserializenotonlyproperties,butalsofields.Youcanevenserializenon-publicmemberssuchasprivateorprotectedmembers.Andyoudontneedasetonapropertyeither(howeverwithoutasetteryoucanserialize,butnotdeserialize)3.Isabout10%fasterthanXmlSerializertoserializethedatabecausesinceyoudon’thavefullcontroloverhowitisserialize,thereisalotthatcanbedonetooptimizetheserialization/deserializationprocess.4.CanunderstandtheSerializableAttributeandknowthatitneedstobeserialized5.MoreoptionsandcontroloverKnownTypesDisadvantages:
1.Nocontroloverhowtheobjectisserializedoutsideofsettingthenameandtheorder

WhatisSerialization?

Let’sstartwiththebasics.Serializationhasbeenakeypartof.Netsinceversion1.Itisbasicallytheprocessofconvertinganobjectinstanceintoaportableandtransferableformat.Theobjectscanbeserializedintoallsortsofformats.SerializingtoXmlismostoftenusedforitsinteroperability.Serializingtobinaryisusefulwhenyouwanttosendtheobjectfromone.Netapplicationtoanother..Netevensupportstheinterfacesandbaseclassestobuildyourownserializes.Therearelibrariesouttheretoserializetocommadelimitedstrings,JSON,etc.Deserializationisbasicallythereverseofserialization.Itstheprocessoftakingsomedata(Xml,binary,etc)andconvertingitbackintoanobject.

WhatistheXmlSerialzer?

ForthosethatmaynotbefamiliarwithSystem.Xml.Serialization.XmlSerializerlet’sgooveritbriefly.Thisisthexmlserializerthathasbeenaroundsince.Netversionone.Toserializeordeserializeanobject,youbasicallyjustneedtocreateaninstanceoftheXmlSerializerforthetypeyouwanttoworkwith,thenjustcallSerialize()orDeserialize().Itworkswithstreams,soyoucouldserializetoanystreamsuchasanMemoryStream,FileStream,etc.
//Createserializerforthetype
System.Xml.Serialization.XmlSerializerxmlSerializer=
newSystem.Xml.Serialization.XmlSerializer(typeof(MyType));

//Serializefromanobjecttoastream
xmlSerializer.Serialize(stream,myInstanceOfMyType);

//Deserializefromastreamtoanobject
myInstanceOfMyType=(MyType)xmlSerializer.Deserialize(stream);

Howevernotjustanyobjectcanbeserialized.Itsupportsanumberofthebasetypesin.Netandmostcustomtypes.ManypeoplethinkthattheSerializableAttributeisrequiredontheclassinorderforittobeserializablebytheXmlSerializer,butthisisnotthecase.ItisgoodpracticetousetheSerializableAttribute,butitnotrequired.Aslongasyourclasscontainsalltypesthattheserializerunderstands,thenitwillwork.YouneedtobreakoutIXmlSerializabletoimplementyourowncustomserializationfortypesthattheXmlSerializercannotunderstand.AnypublicpropertythatisofaknownserializabletypeandhasagetandsetwillbeserializedbytheXmlSerialzer.Thiscanbereferredtoasan“opt-out”approach,becauseyouchosewhatyoudon’twanttoinclude,notwhatyouwanttoinclude.
Thereareanumberofattributesyoucanuseinyourclasstochangehowitisserialized:

System.Xml.Serialization.XmlIgnoreAttribute:Thisisusedtomarkapublicpropertyas“nottobeserialized”.Thisisthe“opt-out”approachusedbytheXmlSerializer.Therearenopropertiesonthisattribute.
System.Xml.Serialization.XmlRootAttribute:Thisisusedontheclassitselftochangethenameornamespaceoftherootnode.Thefollowingpropertiesaresupportedontheattribute:

AttributeName:GetsorsetsthenameoftheXMLattribute.
DataType:GetsorsetstheXSDdatatypeoftheXMLattributegeneratedbytheXmlSerializer.
Form:GetsorsetsavaluethatindicateswhethertheXMLattributenamegeneratedbytheXmlSerializerisqualified.
Namespace:GetsorsetstheXMLnamespaceoftheXMLattribute.
Type:GetsorsetsthecomplextypeoftheXMLattribute.
TypeId:Whenimplementedinaderivedclass,getsauniqueidentifierforthisAttribute.

System.Xml.Serialization.XmlAttributeAttribute:Serializethepropertyasanxmlattribute.Youcanspecifythingssuchasthenametouse(insteadofthepropertyname).Thefollowingpropertiesaresupportedontheattribute:

AttributeName:GetsorsetsthenameoftheXMLattribute.
DataType:GetsorsetstheXSDdatatypeoftheXMLattributegeneratedbytheXmlSerializer.
Form:GetsorsetsavaluethatindicateswhethertheXMLattributenamegeneratedbytheXmlSerializerisqualified.
Namespace:GetsorsetstheXMLnamespaceoftheXMLattribute.
Type:GetsorsetsthecomplextypeoftheXMLattribute.
TypeId:Whenimplementedinaderivedclass,getsauniqueidentifierforthisAttribute.

System.Xml.Serialization.XmlElementAttribute:Serializethepropertyasanxmlelement.Youcanspecifythingssuchasthenametouse(insteadofthepropertyname),whetherornottoserializeitifitisnull,theordertoserializethepropertyinrelativetootherproperites,etc.Thefollowingpropertiesaresupportedontheattribute:

ElementName:GetsorsetsthenameoftheXMLelement.
DataType:GetsorsetstheXSDdatatypeoftheXMLattributegeneratedbytheXmlSerializer.
Form:GetsorsetsavaluethatindicateswhethertheXMLattributenamegeneratedbytheXmlSerializerisqualified.
Namespace:GetsorsetstheXMLnamespaceoftheXMLattribute.
IsNullable:GetsorsetsavaluethatindicateswhethertheXmlSerializermustserializeamemberthatissettonullNothingnullptranullreference(NothinginVisualBasic)asanemptytagwiththexsi:nilattributesettotrue.
Order:Getsorsetstheexplicitorderinwhichtheelementsareserializedordeserialized.
Type:GetsorsetsthecomplextypeoftheXMLattribute.
TypeId:Whenimplementedinaderivedclass,getsauniqueidentifierforthisAttribute.

HereisanexampleclasssetuptousetheXmlSerializer.TheonlythingfancyhereisthatIdon’twanttoserializetheSocialSecuritynumber:
[System.Serializable]
publicclassIndividual
{
privatestringm_FirstName;
privatestringm_LastName;
privateintm_SocialSecurityNumber;

publicstringFirstName
{
get{returnm_FirstName;}
set{m_FirstName=value;}
}

publicstringLastName
{
get{returnm_LastName;}
set{m_LastName=value;}
}

[System.Xml.Serialization.XmlIgnore]
publicintSocialSecurityNumber
{
get{returnm_SocialSecurityNumber;}
set{m_SocialSecurityNumber=value;}
}

publicIndividual()
{
}
publicIndividual(stringfirstName,stringlastName)
{
m_FirstName=firstName;
m_LastName=lastName;
}
}

WhatistheDataContractSerializer?

TheSystem.Runtime.Serialization.DataContractSerializerisnewin.Net3.0andwasdesignedforcontract-firstdevelopmentandspeed.SpecificallyitwasbroughtintobeusedbyWcf,butcanbeusedforgeneralserializationaswell.UsingtheDataContractSerializerisn’tthatmuchdifferentthanusingtheXmlSerializer.Thereareafewmoreoptions,buttheonlyrealkeydifferenceisthatyouuseaWriteObject()methodtoserializeinsteadofaSerialize()methodandaReadObject()methodtodeserializeinsteadofaDeserialize()method.Itworkswiththesametypesofstreams,soyoucanwritetomemory,files,etc.
DataContractSerializerdataContractSerializer=
newDataContractSerializer(typeof(MyType));

//Serializefromanobjecttoastream
dataContractSerializer.WriteObject(stream,myInstanceOfMyType);

//Deserializefromastreamtoanobject
myInstanceOfMyType=(MyType)dataContractSerializer.ReadObject(stream);

Onethingtonote:beforeyoucanusetheDataContactSeriliazer,youmustincludeareferencetoSystem.Runtime.Serialization.mscorelibgivesyousomepartsofSystem.Runtime.Serialization,butyoumustincludethisreferencetogettheDataContactSeriliazerandtheassociatedattributes.



Again,notjustanyobjectcanbeserialized.Itsupportsanumberofthebasetypesin.Netandmostcustomtypes.OneniceadvantagethattheDataContractSerializerhasovertheXmlSerializeristhatitunderstandstheSerializableAttributeandclassesbuiltfortheXmlSerializerorISerializable.SoifyourclassisdeclaredwithanDataContactAttributeanditcontainsatypethatusestheSerializableAttibute,allwillbewell.UnliketheXmlSerializerthoughyoumustdefineeithertheSerializableAttributeortheDataContractAttributeontheclassinorderforittobeserializablebytheDataContractSerializer.
TheDataContactSerializerimplementsan“opt-in”approach.ThebasicallymeansthatyouhavetoexplicitlysaywhatwillbeserializedbyaddingtheDataMemeberAttributetoit.Thenicethingaboutthisisthatthisattributecanbeappliedtofieldsandwellasproperties,youcansetitonanyaccessmodified(private,protected,etc)notjustpublic,andyoucanuseitonpropertiesthatdonothavea“set”.Howeverifyoulabelapropertythatdoesn’thavea“set”,thenyoucanonlyserializethatproperty.Youwon’tbeabletodeserializeitsinceithasnoideahowtosettheproperty.ThisalsomeansyoucantuseitforcommunicationoverWcf.Butyoucanstillusea“privateset”toensurethatyourmodelisclean.However,youcannotspecifythatpropertiesshouldbexmlattributesandcontrolothermorecomplexthingsabouthowthexmlwilllook.Ithurtsnothavingthisflexibility,butbecauseofthisrigidness,theformatishighlypredictableandtheserializercanmakesomebigoptimizations.TheDataContractSerializercanserializeanddeserializeabout10%fasterthantheXmlSerializer.Thiscanbeprettysignificantifyouareworkingwithalotofdata.
Therearereallyonly2attributestouseinyourclass:

System.Runtime.Serialization.DataContactAttribute:Declaresthattheclassisserializableandallowsyoutospecifythenamespaceandnametoserializeitas.ThisissimilartoacombinationoftheSerializableAttributeandXmlRootAttributeintheXmlSerializer.Thefollowingpropertiesaresupportedontheattribute:

Name:Getsorsetsthenameofthedatacontractforthetype.
Namespace:Getsorsetsthenamespaceforthedatacontractforthetype.
TypeId:Whenimplementedinaderivedclass,getsauniqueidentifierforthisAttribute.

System.Runtime.Serialization.DataMemberAttribute:Thisisusedtodeclareapropertyorafieldtobeserialized.Thiscanworkwithanyaccessmodifier.Thefollowingpropertiesaresupportedontheattribute:

EmitDefauleValue:Getsorsetsavaluethatspecifieswhethertoserializethedefaultvalueforafieldorpropertybeingserialized.
IsRequired:Getsorsetsavaluethatinstructstheserializationenginethatthemembermustbepresentwhenreadingordeserializing.
Name:Getsorsetsadatamembername.
Order:Getsorsetstheorderofserializationanddeserializationofamember.Thiscanbeprettypowerfulifyouhavefieldsthatmightdependononeanotherandyoureallyneedtodefinetheorderthatthepropertiesareserializeanddeserializedin.
TypeId:Whenimplementedinaderivedclass,getsauniqueidentifierforthisAttribute.


IfyouaregoingtoworkwiththeDataMemberAttribute,hereisanconcisepostaboutbestpracticesaroundit:http://blogs.msdn.com/drnick/archive/2008/02/22/datamember-best-practices


BelowexampleclasssetuptousetheDatContractSerializer.NoticethatIamexplicitlysettingtheDataMemberAttributeonthepropertiesIwanttoserialize,butnotontheothers.
[DataContract]
publicclassIndividual
{
privatestringm_FirstName;
privatestringm_LastName;
privateintm_SocialSecurityNumber;

[DataMember]
publicstringFirstName
{
get{returnm_FirstName;}
set{m_FirstName=value;}
}

[DataMember]
publicstringLastName
{
get{returnm_LastName;}
set{m_LastName=value;}
}

publicintSocialSecurityNumber
{
get{returnm_SocialSecurityNumber;}
set{m_SocialSecurityNumber=value;}
}

publicIndividual()
{
}
publicIndividual(stringfirstName,stringlastName)
{
m_FirstName=firstName;
m_LastName=lastName;
}
}

OneotherimportantthingtotalkaboutwiththeDataContractSerializeraretheServiceKnownTypeAttributeandKnownTypeAttributeattributes.ThesearesimilartotheXmlIncludeAttributeusedbytheXmlSerializer.WhenusedinWcf,theseidentifywhattypesshouldberepresentedintheWSDLthatisgenerated.
TheKnownTypeAttributespecifiestypesthatshouldberecognizedbytheDataContractSerializerwhenserializinganddeserializingatype.Itisappliedtoaclassandbasicallyspecifieswhatothertypesareusedintheclass.Youdon’tneedtospecifyknown.Nettypes,butanycustomclassesshouldbeaddedhere.Thisattributecanbeusedmultipletimestoidentifymultipletypes.
[DataContract]
[KnownType(typeof(MyOtherType))]
publicclassMyType
{
[DataMember]
publicMyOtherTypeTheOtherType;
}

[DataContract]
publicclassMyOtherType
{
[DataMember]
publicstringMyValue;
}

TheServiceKnownTypeAttributespecifiesknowntypestobeusedbyaservicewhenserializingordeserializing.ItisappliedtoaServiceContractortoanOperationContractandspecifieswhattypesareusedinthemethods.Again(liketheKnownTypeAttribute),youdon’tneedtospecifyknown.Nettypesandthisattributecanbeusedmultipletimestoidentifymultipletypes.
[ServiceContract]
[ServiceKnownType(typeof(MyType))]
[ServiceKnownType(typeof(MyOtherType))]
publicinterfaceMyService
{
[OperationContract]
[ServiceKnownType(typeof(YetAnotherType))]
voidMyMethod();
}

WhatabouttheNetDataContractSerializer?

Ihaven’treallymentionedthisyetbecauseitisjustliketheDataContractSerializer,butthereisalsoaSystem.Runtime.Serialization.NetDataContractSerializer.ItdiffersfromtheDatContactSerializerinthatitincludesCLRtypeinformationintheserializedxml,whereastheDataContractSerializerdoesnot.SoitcanonlyworkiftheserializingandderserializingendssharethesameCLRtypes.ThenicethingaboutthisserializeristhatsincetheCLRtypeinformationissentaround,youdon’thavetoimplementtheServiceKnownTypeAttirbuteorKnownTypeAttribute.LiketheDataContractSerializeritcanworkserializetypesthatimplementeithertheDataContractAttribute,SerializableAttribute,orISerializable.
Idon’trecommendusingthisserializeroften.Ifpossibleyoushoulddeclareyourknowntypesexplicitlyforbetterunderstandofthecodeandofcourseforthegreaterinteroperability.

Whyanotherxmlserializer?

Sowhytheneedtoevencreateanotherxmlserializer?TheXmlSerializerhasserveduswellovertheyears.Wellpartofititspeed.SincetheDataContractsarefastertoserializebecausethestructureispredictableandcanbemorehighlyoptimized.Thisresultsinabouta10%performancegain.IfyouareworkingwithpureWcfthegaininspeedisprobablyworththetradeoffinlossofcontroloverwhattheXmlistolooklike.Sometimesyoumightneedtocontrolwhatthexmllooksliketogetittofittosomeotherschema.Ifthatisthecase,thenyouwillwanttoswitchtotheXmlSerializer.
Thereismoretothestory.Microsoftwantsusthinkofintermsof“Contracts”withWcf.Weoftenheartheterm“ContractFirstDevelopment”.SomeofthisprincipalisalreadyinplaybyforcingallWcfServicestobedefinedinaninterface(contract).IntheolddaysofpureWebServices,youcouldjusttagaclassasWebServiceandyoudidn’tneedaseparateinterfaceorcontract.Insomerespects,theDataContractSerializerispushingusdownthisroutetoo.BydeclaringaclassasaDataContractandexplictilysettingtheDataMembers,youarebuildingacontractofhowtheclassshouldlook.OnecouldarguethatyoucoulddothisthroughtheSerializableattribute,howeveryoudon’tdefinewhatgoesinthecontract.Insteadyouonlyspecifywhatisn’tsupposetobeserializedandtheserializerdecideswhatisshouldserialize.Thereisnowaytolookattheclassorusereflectionandreallygetagoodfeelforthedatacontractfortheclass.WhilewiththeDataContractandDataMemberattributes,youcouldusereflectiontoseeexactlywhatthecontractis.

HowtochangeWcftouseadifferentserializer?

BydefaultWcfusestheDataContactSerializer,soifyouwanttouseit,youneedtodonothingelse.IfyouwanttousetheXmlSerializerthrough,allyouneedtodoisaddtheSystem.ServiceModel.XmlSerializerFormatAttributetothecontactinterface.Thenicethingaboutthisattributeisthatitcanbeappliedtotheentireservicecontract,orjusttoanoperationcontract.SoyoucouldkeeptheentireserviceasawholeusingtheDataContractSerializer,butonlythemethodsyouchosetousetheXmlSerializer.
[ServiceContract]
[XmlSerializerFormat]
publicinterfaceMyService
{
[OperationContract]
[XmlSerializerFormat]
voidMyMethod();
}

YoucanalsosettheservicetousetheXmlSerilizerbydefault,butspecifywhichmethodsusetheDataContractSerializerwiththehelpoftheSystem.ServiceModel.DataContractFormatAttribute:
[ServiceContract]
[XmlSerializerFormat]
publicinterfaceMyService
{
[OperationContract]
[DataContractFormat]
voidMyMethod();
}

NowwhataboutchangingtousetheNetDataContractSerializer.OrwhatifIwanttouseadifferentserializerorcreatemyown?InordertodothisyouneedtocreateacustomoperationbehaviorusingtheIOperationBehaviorinterfaceandtheAttributeclass.
HereisanexampleofacustomoperationbehaviorwrittentousetheNetDataContractSerialier.Youcouldusethis,buildyourown,ormodifyittoworkwithadifferentserializer.

publicclassNetDataContractFormatAttribute:Attribute,IOperationBehavior
{
publicvoidAddBindingParameters(OperationDescriptiondescription,BindingParameterCollectionparameters)
{
}
publicvoidApplyClientBehavior(OperationDescriptiondescription,ClientOperationproxy)
{
ReplaceDataContractSerializerOperationBehavior(description);
}
publicvoidApplyDispatchBehavior(OperationDescriptiondescription,DispatchOperationdispatch)
{
ReplaceDataContractSerializerOperationBehavior(description);
}
publicvoidValidate(OperationDescriptiondescription)
{
}
privatestaticvoidReplaceDataContractSerializerOperationBehavior(OperationDescriptiondescription)
{
DataContractSerializerOperationBehaviordcs=description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if(dcs!=null)
description.Behaviors.Remove(dcs);
description.Behaviors.Add(newNetDataContractSerializerOperationBehavior(description));
}
publicclassNetDataContractSerializerOperationBehavior:DataContractSerializerOperationBehavior
{
privatestaticNetDataContractSerializerserializer=newNetDataContractSerializer();
publicNetDataContractSerializerOperationBehavior(OperationDescriptionoperationDescription):base(operationDescription){}
publicoverrideXmlObjectSerializerCreateSerializer(Typetype,stringname,stringns,IList<Type>knownTypes)
{
returnNetDataContractSerializerOperationBehavior.serializer;
}
publicoverrideXmlObjectSerializerCreateSerializer(Typetype,XmlDictionaryStringname,XmlDictionaryStringns,IList<Type>knownTypes)
{
returnNetDataContractSerializerOperationBehavior.serializer;
}
}
}Onceyouhavethisyoucanjustmarkupyourservicelikebeforeusingthenewattribute:
[ServiceContract]
[NetDataContractSerializerFormat]
publicinterfaceMyService
{
[OperationContract]
voidMyMethod();
}

Onceyouhavethisyoucanjustmarkupyourservicelikebeforeusingthenewattribute:
[ServiceContract]
[NetDataContractSerializerFormat]
publicinterfaceMyService
{
[OperationContract]
voidMyMethod();
}

Whentousewhichserializer?

ForWcf,youshouldprefertousetheDataContractSerializer.Ifyouneedfullcontroloverhowthexmllooksthough,youshouldgobacktotheXmlSerializer.Ifyouaredoinggeneralserialization,itisuptoyou,butIwouldweighouttheadvantagesanddisadvantages.IwouldstillprefertheDataContractSerializerforthesamereasonsIpreferitforWcf.IdonotrecommendusingtheNetDataContractSerializerunlessyouhaveto.Youcanlosetoomuchinteroperabilityanditsnotasdescriptive.
Ifyouneedsomecustomxmlserializer,byallmeansgoaheadandimplementit.Wcfsupportsanyserializeryoucanthrowatit.Justbecarefulnotto“reinventthewheel”.TheXmlSerializerisveryconfigurableandmaysuityourneeds.Ifthatdoesn’twork,thenISerializablegivesyoufullcontrol.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐
章节导航