.Net → 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.


