【WCF】更改DataContractSerializer的输出格式
WCF所支持的序列化格式分为Xml和DataContract两种(以下简称Xml格式和DataContract格式)。个人认为,Xml序列化格式是为了达到协议兼容而保留下来的传统格式。比如通过WCF实现基于xup协议的UI架构时,为了与xup协议保持兼容,在设置WCF属性时,建议采用Xml格式;而DataContract格式则是WCF提供的一种新的序列化格式。默认情况下,WCF采用DataContract格式。如需要在WCF中使用Xml格式,我们所要做的事情非常简单:在服务契约接口以及相应的契约方法上应用XmlSerializerFormatAttribute特性,并在使用svcutil.exe实用工具生成客户端代码时带上/ser:XmlSerializer参数。Xml格式和DataContract格式的优缺点大致如下:
- Xml格式:序列化方式可以通过XmlRootAttribute、XmlElementAttribute以及XmlAttributeAttribute等特性进行控制,也可以使用XmlAttributeOverrides类对序列化方式进行更深层次的自定义,因此它能很方便地兼容已有的通讯协议,使得应用程序符合一定的通讯标准;其缺点就是速度不及DataContract格式,对于需要序列化的成员,必须是公有成员,而且同时实现getter和setter
- DataContract格式:速度比Xml格式快,因为它正好缺少Xml格式的优点:无法自定义序列化方式。其优点是,相对Xml格式来讲,它支持更多类型的序列化,而且其成员的受访级别可以是受保护的,甚至是私有的;DataContract格式没有Xml格式中类似XmlElementAttribute等控制序列化方式的特性
因此,当你的应用程序无需兼容标准协议,并且你不需要对传输的信息作调试时,建议采用DataContract格式。但也有时候我们既希望保证速度,又希望能够在应用程序里输出response的xml信息以便查错;此时,我们会使用DataContractSerializer类来将获得的response信息序列化成xml。当走到这一步时,你会发现,你获得的xml信息会是下面的样子:
- <?xml version="1.0" encoding="utf-8"?><ApResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Apworks.UI.Protocols.Response"><SessionId>55b494dc-430d-407e-9c5b-62ff9cc86804</SessionId><Type>Startup</Type><ServerInfo><Name>Apworks UI Experimental Server</Name><Version>1.0</Version></ServerInfo><StartupInfo><WindowList xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><d3p1:string>wndHelloWorld</d3p1:string><d3p1:string>wndComplex</d3p1:string></WindowList></StartupInfo><InSessionInfo><ElementHolderXml i:nil="true" /><EventSelectors i:nil="true" /><UIAttrUpdates i:nil="true" /></InSessionInfo><ShutdownInfo /><ErrorInfo><Message i:nil="true" /></ErrorInfo></ApResponse>
其实,我们可以使用XmlWriter和XmlWriterSettings类来自定义xml的输出格式。通过类似下面的代码(注意粗体部分),我们获得了带有缩进效果的xml字符串,增加了xml的可读性。
- this.clientProxy.Processed += (sender, e) =>
- {
- XmlWriterSettings settings = new XmlWriterSettings { Indent = true, Encoding=Encoding.UTF8 };
- settings.IndentChars = "\t";
- DataContractSerializer s = new DataContractSerializer(typeof(ApResponse));
- MemoryStream ms = new MemoryStream();
- XmlWriter writer = XmlWriter.Create(ms, settings);
- s.WriteObject(writer, e.Response);
- writer.Flush();
- writer.Close();
- string xml = Encoding.ASCII.GetString(ms.ToArray());
- this.DoProcessed(sender, xml);
- };
输出效果如下:
- <?xml version="1.0" encoding="utf-8"?>
- <ApResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Apworks.UI.Protocols.Response">
- <SessionId>5fab9547-06c3-4fc9-8e20-43eafa3bb74a</SessionId>
- <Type>Startup</Type>
- <ServerInfo>
- <Name>Apworks UI Experimental Server</Name>
- <Version>1.0</Version>
- </ServerInfo>
- <StartupInfo>
- <WindowList xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
- <d3p1:string>wndHelloWorld</d3p1:string>
- <d3p1:string>wndComplex</d3p1:string>
- </WindowList>
- </StartupInfo>
- <InSessionInfo>
- <ElementHolderXml i:nil="true" />
- <EventSelectors i:nil="true" />
- <UIAttrUpdates i:nil="true" />
- </InSessionInfo>
- <ShutdownInfo />
- <ErrorInfo>
- <Message i:nil="true" />
- </ErrorInfo>
- </ApResponse>