Georged Weblog

Have you georged your mind?

XmlPleaseIgnore

There is a handy class UriBuilder which, unlike Uri, allows full read-write access to all the components of Uri. However, problems started when I tried to serialise it using XmlSerializer. The following code:

using System;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
public class XmlPleaseIgnore
{
    public static void Main()
    {
        UriBuilder b = new UriBuilder("http", "localhost", 80, "/test/default.aspx");
        XmlSerializer x = new XmlSerializer(b.GetType());
        x.Serialize(Console.Out, b);
    }
}

quickly produced this:

Unhandled Exception: System.InvalidOperationException: There was an error reflecting type 'System.UriBuilder'. ---> System.InvalidOperationException: System.Uri cannot be serialized because it does not have a default public constructor.

A bit of digging revealed that UriBuilder.Serialize method

...converts the public fields and read/write properties of an object into XML. It does not convert methods, indexers, private fields, or read-only properties. To serialize all of an object's fields and properties, both public and private, use the BinaryFormatter.

And, of course, Uri property of UriBuilder is read-only property and, to make the matter worse, it does not have public default constructor. If it were my class I would apply XmlIgnore attribute to the member and that would do the trick. As I found, with a bit of code it can be done for external classes as well:

using System;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
public class XmlPleaseIgnore
{
    public static void Main()
    {
        // add XmlIgnore attribute and attach it to Uri member of UriBuilder class
        XmlAttributes attrs = new XmlAttributes();
        attrs.XmlIgnore = true;
        XmlAttributeOverrides over = new XmlAttributeOverrides();
        over.Add( typeof(UriBuilder), "Uri", attrs);
        
        UriBuilder b = new UriBuilder("http", "localhost", 80, "/test/default.aspx");
        XmlSerializer x = new XmlSerializer(b.GetType(), over); // override attributes
        x.Serialize(Console.Out, b);
    }
}
And here is the output:
xml version="1.0" encoding="utf-8" ?>
<UriBuilder
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Fragment />
<Host>localhostHost>
<Password />
<Path>/test/default.aspxPath>
<Port>80Port>
<Query />
<Scheme>httpScheme>
<UserName />
> 

Note that attribute is applied to a member of a class and therefore I can also serialise my own classes which have UriBuilder as a member variable.

Sweet.

Posted: Nov 06 2003, 12:05 PM by georged | with 3 comment(s)
Filed under:

Comments

Adrian Florea said:

Very sweet indeed! :-) Thanks for the point
# March 2, 2004 8:01 AM

TrackBack said:

^_^,Pretty Good!
# April 9, 2005 1:00 PM

TrackBack said:

^_^,Pretty Good!
# April 15, 2005 3:21 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)