Serialize NameValueCollection

As I said before one of new features in new version of BlogML is Blog Extended Properties.  Extended Properties are a collection of property names and their corresponding values about blogs.

Recently I tried to implement them in .NET APIs.  At first glance I started with IDictionary<string, string> and implemented this interface and inherited my Extended Properties class from this base class but after seeing this post from Darren, removed that implementation and tried NameValueCollection.  the problem with NameValueCollection is it's not Serializable by default.

In this KB article Microsoft has described this situation and has recommended a solution to use SoapFormatter to Serialize and Deserialize NameValueCollections.  But as we serialize everything manually in BlogML I couldn't use it.  In the process of finding a solution, I found this article by James Crowley about a technique to serialize NameValueCollections but it didn't fit to my needs so I started modifying it.  While I was working on this and couldn't get any result I talked to Darren about this problem and he decided to implement Extended Properties as List<SerializableKeyValuePair<string, string>> and did it.

Today I worked more on my approach to make it work and could get the result.

First I created a Serializable class for my extended_properties then implemented IXmlSerializable interface for it.  This class contains a NameValueCollection as a property but I marked it as XmlIgnore to ignore it from Serialization.  Instead, I serialized it manually using the interface and the result was following class:

using System;

using System.Collections.Specialized;

using System.Xml;

using System.Xml.Schema;

using System.Xml.Serialization;

 

namespace NameValueCollectionSerializing

{

    [Serializable]

    public class extended_properties : IXmlSerializable

    {

        #region Private members

        private NameValueCollection properties;

        #endregion

 

        #region Constructors

        public extended_properties()

        {

        }

 

        public extended_properties

            (NameValueCollection properties)

        {

            this.properties = properties;

        }

        #endregion

 

        #region Properties

        [XmlIgnore]

        public NameValueCollection Properties

        {

            get { return this.properties; }

            set { this.properties = value; }

        }

        #endregion

 

        #region IXmlSerializable Members

        XmlSchema IXmlSerializable.GetSchema()

        {

            return null;

        }

 

        void IXmlSerializable.ReadXml(XmlReader reader)

        {

            this.properties = new NameValueCollection();

            while (reader.MoveToNextAttribute())

                this.properties.Add

                    (reader.Name, reader.Value);

 

            reader.Read();   

        }

 

        void IXmlSerializable.WriteXml(XmlWriter writer)

        {

            foreach (string key in this.properties.Keys)

            {

                writer.WriteStartElement("property");

                string value = this.properties[key];

                writer.WriteAttributeString(key, value);

                writer.WriteEndElement();

            }

        }

        #endregion

    }

}

After implementing this class, I could get what I wanted.  The code to test this class is:

private void button1_Click(object sender, EventArgs e)

{

    string FilePath = Path.GetDirectoryName

        (Application.ExecutablePath)

        + "\\ExtendedProperties.xml";

 

    NameValueCollection Properties =

        new NameValueCollection();

    Properties.Add("Trackbackenabled", "True");

    Properties.Add("CommentModeartion", "1 Month");

    extended_properties exProperties =

        new extended_properties(Properties);

 

    XmlSerializer xs = new XmlSerializer

        (typeof(extended_properties));

    StreamWriter sw = new StreamWriter(FilePath);

    xs.Serialize(sw, exProperties);

    sw.Close();

 

 

    extended_properties exProperties2;

    StreamReader sr = new StreamReader(FilePath);

    exProperties2 =

        (extended_properties)xs.Deserialize(sr);

    sr.Close();

 

    System.Diagnostics.Process.Start

        ("notepad", FilePath);

}

Now playing: Michael Jackson - Billie Jean

[advertisement] Axosoft OnTime 2008 is four developer tools in one: bug tracking, project wiki, feature management, and help desk. It manages your development process so developers can focus on coding. Installed or Hosted – Free Single-user license -- Free 30-day team trial.

3 Comments : 08.11.06

Feedbacks

 avatar
#1
Tim Erwin
05.16.2007 @ 10:03 AM
Thanks a lot for your code example. It helped alot. Maybe I don't understand exactly what you are doing, but I was able to adapt your code to this and replace NameValueCollection with PropertyCollection where I wanted to use it: /// /// http://creativecommons.org/licenses/by/3.0/ /// adapted from http://nayyeri.net/archive/2006/08/11/serialize-namevaluecollection.aspx /// [Serializable] public class PropertyCollection: System.Collections.Specialized.NameValueCollection, IXmlSerializable { #region IXmlSerializable Members void IXmlSerializable.ReadXml(XmlReader reader) { while ( reader.Read( ) ) { reader.MoveToAttribute( "key" ); string Key = reader.Value; reader.MoveToAttribute( "value" ); string Value = reader.Value; this.Add( Key, Value ); } } void IXmlSerializable.WriteXml(XmlWriter writer) { foreach (string Key in this.Keys) { writer.WriteStartElement("Property"); string Value = this[Key]; writer.WriteAttributeString("key", Key); writer.WriteAttributeString("value", Value); writer.WriteEndElement(); } } public System.Xml.Schema.XmlSchema GetSchema( ) { return null; } #endregion }
 avatar
#2
Al
09.05.2008 @ 7:38 AM

Hi!

I'm 100% there is a bug in

void IXmlSerializable.ReadXml(XmlReader reader)

 avatar
#3
angerico
11.11.2008 @ 4:00 AM

When IXmlSerializable.ReadXml() hits this line:

while (reader.MoveToNextAttribute())

it expects the xmlreader to be positioned already at a "property" element. If you're getting an error or the function isn't working, try to move the reader to a "property" element first before parsing it.

Leave a Comment