Welcome to WindowsClient.net | Sign in | Join

BestSnowman's WPF Blog

Sponsors





  • advertise here

When the Uri class just won’t work…

I recently had some issues with one of my projects where the application settings would just silently fail. It turns out that the XmlSerializer doesn’t like the Uri class because it has no default constructor. It turns out I’m not the first one to notice this and the SerializableUri class is very handy and Microsoft won’t be fixing it. (Special thanks to Clint Rutkas for help figuring that one out)

SerializableUri works if you are using the XmlSerializer but since I wanted to do WPF databinding and Uri is immutable I decided to write my own class. The application I am working on allows the user to enter a Uri of a WCF service to connect to that can operate on variable port numbers and schemes so I decided to create my own class called Url (real original huh…). I took some tricks from SerializableUri and included the implicit operators so you can use it basically interchangeably with Uris. Instead of doing my own parsing I’m just using the Uri class to do the parsing. It also implements INotifyPropertyChanged so you can do two way binding in WPF.

using System;
using System.ComponentModel;

/// <summary>
/// Since the Uri class is immutable and not XML serializable this is a class to
/// use for serialization and databinding
/// </summary>
public class Url : INotifyPropertyChanged
{
    #region Fields

    private string host;

    private int port;

    private string pathAndQuery;

    private string scheme;

    #endregion

    #region Constructors

    public Url()
    {
    } 

    public Url(string url)
    {
        ParseString(url);
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Url"/> class.
    /// </summary>
    /// <param name="uri">The URI.</param>
    public Url(Uri uri)
    {
        ParseUri(uri);
    } 

    public Url(string scheme, string host, int port, string pathAndQuery)
    {
        this.Scheme = scheme;
        this.Host = host;
        this.Port = port;
        this.PathAndQuery = pathAndQuery;
    }

    #endregion

    #region Events

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    #region Properties 

    public string AbsoluteUrl
    {
        get
        {
            return this.ToString();
        }
        set
        {
            ParseString(value);
        }
    } 

    public string Host
    {
        get { return this.host; }
        set
        {
            if (this.host != value)
            {
                this.host = value;
                NotifyPropertyChanged("Host");
            }
        }
    } 

    public int Port
    {
        get { return this.port; }
        set
        {
            if (this.port != value)
            {
                this.port = value;
                NotifyPropertyChanged("Port");
            }
        }
    }

    public string PathAndQuery
    {
        get { return this.pathAndQuery; }
        set
        {
            if (this.pathAndQuery != value)
            {
                this.pathAndQuery = value;
                NotifyPropertyChanged("PathAndQuery");
            }
        }
    } 

    public string Scheme
    {
        get { return this.scheme; }
        set
        {
            if (this.scheme != value)
            {
                this.scheme = value;
                NotifyPropertyChanged("Scheme");
            }
        }
    } 

    public Uri Uri
    {
        get
        {
            return new Uri(this.AbsoluteUrl);
        }
    }

    #endregion

    #region Implicit Operators

    public static implicit operator Uri(Url uri)
    {
        return uri.Uri;
    }

    public static implicit operator Url(Uri uri)
    {
        return new Url(uri);
    }

    #endregion

    #region Methods 

    private void NotifyPropertyChanged(string info)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(info));

            // If any property changes the AbsoluteUrl also changes since it is just
            // a composition of the other properties.
            if (info != "AbsoluteUrl")
            {
                NotifyPropertyChanged("AbsoluteUrl");
            }
        }
    }

    /// <summary>
    /// Parses the string.
    /// </summary>
    /// <param name="url">The URL.</param>
    private void ParseString(string url)
    {
        // Using the Uri's parsing for simplicity sake
        ParseUri(new Uri(url));
    }

    /// <summary>
    /// Parses the URI.
    /// </summary>
    /// <param name="parseUri">The parse URI.</param>
    private void ParseUri(Uri parseUri)
    {
        this.Scheme = parseUri.Scheme;
        this.Host = parseUri.Host;
        this.Port = parseUri.Port;
        this.PathAndQuery = parseUri.PathAndQuery;
    }


    public override string ToString()
    {
        string formatString = "{0}://{1}:{2}/{3}";

        return string.Format(formatString, this.Scheme, this.Host, this.Port, this.PathAndQuery);
    }

    #endregion
}

Posted: Jan 14 2009, 07:53 PM by mattnewman
Filed under: ,

Comments

No Comments

Page view counter