Over a million developers have joined DZone.

C# – XML Element Value Generic Extention Method

·

Recently, I was working on integrating a help desk API into one of our applications.  The API would return XML and I was using LINQ-To-XML to get the values of the elements.  However, a number of the elements in the API were allowed to be null, like a field for the completed date of a help desk ticket.  So, I started out writing my code like this…

// constructor for Ticket class
public Ticket(XElement element)
{
     AssignedDate = (!string.IsNullOrEmpty(element.Element("assigned-date").Value)) ? DateTime.Parse(element.Element("assigned-date").Value) : (DateTime?)null;
 
     // .... on and one for about 40 elements
}

I looked back and thought I should come up with a better way of getting the data from the Element and into the datatype that I needed.  So I came up with this generic extension method…

/// <summary>
/// Gets the value of the element.  Will convert the value to specified type if
///    possible.  If not possible, will return default value for type.
/// </summary>
/// <typeparam name="T">Type that should be returned</typeparam>
/// <param name="ele"></param>
/// <returns></returns>
public static T GetElementValue<T>(this XElement ele)
{
    // if the element is null, then return the default
    if (ele == null)
        return default(T);
 
    // if value is blank or null, just return the default value
    //   for the type.
    if (string.IsNullOrEmpty(ele.Value))
        return default(T);
 
    // since the type of the Value property is a string, no need
    //   to do anything fancy.  Just return the value.
    if (typeof(T) == typeof(string))
        return (T)Convert.ChangeType(ele.Value, typeof(T));
 
    // creates new object of type T to store converted value
    T newObject = default(T);
 
    // check to see if it's a nullable type.  If so, get the underlying
    //   type.
    // Nullable types don't have a Parse method.  Therefore, we need the
    //   underlying type so we can call the Parse method through reflection
    //   to convert the value.
    PropertyInfo[] properties = typeof(T).GetProperties();
    Type underlyingType = typeof(T);
 
    // Nullable types will have two properties.  The first is the HasValue
    //   property.  The second is the underlying type.  However, some other
    //   types(such as String), and custom classes/structs could also have
    //   only two properties.  So we check to make sure that there are only
    //   2 properties, then we make sure the first property is the HasValue
    //   property.  Theoretically, this could still give a false positive.
    if (properties.Count() == 2 &&
        string.Equals(properties[0].Name, "HasValue", StringComparison.InvariantCultureIgnoreCase))
        underlyingType = properties[1].PropertyType;
 
    try
    {
        // calls Parse method for the type
        MethodInfo method = underlyingType.GetMethod("Parse", new[] { typeof(string) });
        newObject = (T)method.Invoke(null, new[] { ele.Value });
    }
    catch (Exception)
    {
        throw;
    }
 
    return newObject;
}

Now with this extension method, it really cuts down on the amount of code I have to write.  I can now use it like this..

public Ticket(XElement element)
{
     AssignedDate = element.Element("assigned-date").GetElementValue<DateTime?>();
}

I hope this can help out somebody.

Topics:

Published at DZone with permission of Ryan Alford, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}