The other day we came across this small thing while writing some sample code for our docs.
We can control the way our CLR arrays are serialized in a well-known way by using XmlSerializer and the XmlArrayAttribute and XmlArrayItemAttribute attributes.
For example having a type like this...
[XmlType(TypeName="Family")]
public class Family
{
[XmlArray(ElementName = "Members")]
[XmlArrayItem(ElementName = "Name")]
public string[] Members;
}
...could produce XML as follows by leveraging XmlSerializer.
<Family xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Members>
<Name>A</Name>
<Name>B</Name>
<Name>C</Name>
<Name>D</Name>
</Members>
</Family>
Now, if we define a bare WCF data contract to represent the same family it would look like this:
[DataContract]
class Family
{
[DataMember]
public string[] Members;
}
The DataContractSerializer (DCS) produces the following XML for an instance of the Family class:
<Family xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Client">
<Members xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:string>A</d2p1:string>
<d2p1:string>B</d2p1:string>
<d2p1:string>C</d2p1:string>
<d2p1:string>D</d2p1:string>
</Members>
</Family>
But if we want to make it look equivalent to the XML generated for the XmlSerializer-based Family document instance, how could we do that?
There is a solution. Looking at the following screenshot from Lutz's fantastic Reflector we can see there are some attributes we can use to massage the XML spit out by DCS.
So, instead of using an array, you need to use a collection type marked with the CollectionDataContractAttribute (you can derive a type from an existing collection type and add the attribute). The attribute has properties that can be used to customize array item names, etc.
E.g.:
[DataContract(Name="Family")]
class Family
{
[DataMember(Name="Members")]
public MemberList Members;
}
[CollectionDataContract(ItemName="Name")]
class MemberList : List<string> { }
Feel free to download a small demo solution for WinFX Beta 2.
Humm, is it just me, or does that somehow seems like a step backwards? :)
Posted by: Tomas Restrepo | 06/21/2006 at 03:26 PM
Hello Christian, This example looks very interesting but do you know if it is possible to implement a Custom DCS that would serialize this NHibernate class (PersistentCollection) : http://www.koders.com/csharp/fid371A022994372753EBD5ADDC91CAD300F6217E67.aspx The idea is to pass (I know this is not recommended in the SOA best practices) a collection of entities (or Proxies) between a WCF service and a remote client. Thanx. Sam
Posted by: Sam | 06/26/2006 at 01:51 PM