Compartilhar via


Serializing an object of the KeyValuePair Generic class

Consider the following piece of C# code running in .NET framework 2.0

static void Main(string[] args)
{
List<KeyValuePair<string, int>> foobar = new List<KeyValuePair<string, int>>();
foobar.Add(new KeyValuePair<string, int>("test1", 1));
foobar.Add(new KeyValuePair<string, int>("test2", 2));

XmlSerializer serializer = new XmlSerializer(typeof(List<KeyValuePair<string, int>>));
using (Stream stm = File.Create("foo.txt"))
{
serializer.Serialize(stm, foobar);
}
}

'KeyValuePair' is a new generic class that has been added to the .NET framework in version 2.0. BTW i think KeyValuePair is the second most natural and 'easy-to-guess-usage' name in programming jargon.( The hands down winner is 'int').

On successful execution the expected output is
<?xml version="1.0"?>
<ArrayOfKeyValuePairOfStringInt32 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<KeyValuePairOfStringInt32>
<key>test1</key>
<value>1</value>
</KeyValuePairOfStringInt32>
<KeyValuePairOfStringInt32>
<key>test2</key>
<value>2</value>
</KeyValuePairOfStringInt32>
</ArrayOfKeyValuePairOfStringInt32>

But the output you would see is
<?xml version="1.0"?>
<ArrayOfKeyValuePairOfStringInt32 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
<KeyValuePairOfStringInt32 />
<KeyValuePairOfStringInt32 />
</ArrayOfKeyValuePairOfStringInt32>

As we clearly see neither the value nor the key gets serialized. If you had played around with the beta bits of VS 2005 and .NET FW 2.0 you would have had the key and value serializing properly.

BTW, Robert Wlodarczyk(who runs this cool blog - https://blogs.msdn.com/rwlodarc/) ran in to this issue in his real world app and narrowed it down to the KeyValuePair. If you are a die hard Imaging and media fan excited about Avalon/WinFX, you've got to bookmark his blog.

The issue turns out to be the following
1) The 'key' and 'value' members are implemented as 'Read-only' properties in .NET FW 2.0. They dont have a set accessor method.
2) The XmlSerializer class, by design, will not serialize read-only properties. In other words, properties that don't have a set accessor will not be serialized using the XmlSerializer class. Note that, you can trick the serializer in to doing the job by having an 'empty' set accessor function for a property of your class. 

From (1) and (2) it turns out that the KeyValuePair cannot be meaningfully serialized.
Also, You can suspect this to be the issue if you run in to cases of missing members during serialization of the Framework classes( or third party classes without source code).

Comments

  • Anonymous
    October 06, 2006
    The comment has been removed

  • Anonymous
    November 12, 2006
    The comment has been removed

  • Anonymous
    September 15, 2009
    Just google serializeable Dictionary. This blog is nonsense.

  • Anonymous
    November 16, 2010
    VS 2010 - C# 4.0 still the same problem like 5 years ago!

  • Anonymous
    April 14, 2011
    thanks for the blog post :)

  • Anonymous
    April 21, 2011
    All I can say is the design does not meet real world requirements. Also XmlSerializer throw an exception instead of serializing erroneous data. Thanks for the post.

  • Anonymous
    May 09, 2014
    C# 4 I also not really understand why we have to develop own implementation for this in 2014.. It should be work out of box.        [Serializable]        [XmlType(TypeName = "KeyValue")]        public class KeyValuePaird<K, V>        {            public K Key            { get; set; }            public V Value            { get; set; }            public KeyValuePaird() { ;}            public KeyValuePaird(K key, V val)            {              Key = key;              Value = val;            }        }