I have created a few very useful extension methods for handling the System.Xml.Linq namespace that I use all the time. I’ve had positive feedback on this before (and it showed up in this post) and now I had to create a couple of extra extensions just to make my life even easier. The way I work with these extensions is when I don’t care to handle null’s and just want to return the value of an element or an attribute who’s name I know. If the value is an empty string you can bet I have a test that catches those scenarios. Like let’s say I want to read a configuration xml that I have created myself before hand. Or someone else’s xml that is very unlikely to change without my knowledge. I will put all this code up on git hub.
To show what I mean I’ll start with what I used to be doing.
var value = enumerableElements.Single(x => x.Name == "foo").Attribute("bar").Value;
With a bunch of the above statements in your code it becomes completely impossible to understand what the hell I was thinking / not thinking when I wrote the code. I write code for myself mostly and I am extremely picky with my code for that specific reason. What is really going on in Linq to Xml is like in most of the things that ships with .NET. It’s a very generic framework that you can build on top of and That’s the whole fun of it all. :)
So what we want to do above is to get the attribute value easily and we don’t care about checking for nulls, it should return the default value if we can’t find the attribute. Let’s start with from the end with getting the attribute value. That could (and will) look like:
public static string GetAttributeValue(this XElement element, string attributeName)
{
XAttribute attribute = element.Attribute(attributeName);
return attribute != null ? attribute.Value : string.Empty;
}
The above is the core, it should never throw any exceptions unless the situation of course is exceptional but in that case I don’t mind so much. The next part is debatable if it should be done but I do it anyway.
public static string GetAttributeValueFromElement(this IEnumerable<XElement> elements,
string elementName, string attributeName)
{
var element = elements
.Descendants(elementName)
.FirstOrDefault(x => x.Name == elementName);
return element.GetAttributeValue(attributeName);
}
Great stuff I just made my own life a bit easier but I believe I can take it one step further without breaking too many things. What if we easily could get rid of needed conversions after retrieving the string value and skip to getting the converted value? Imagine this code, it’s pretty common:
foo.ValidatedAt = DateTime.Parse(validation.GetElementValue("timestamp"));
We can semi-easily simply GetElementValue even more using generics. The above can be shortened to:
public static T GetAttributeValue<T>(this XElement element, string attributeName)
{
XAttribute attribute = element.Attribute(attributeName);
return attribute != null
? Converts.To<T>(attribute.Value)
: Converts.To<T>(string.Empty);
}
Now the call to GetAttributeValue would be shortened to.
foo.ValidatedAt = validation.GetElementValue<DateTime>("timestamp");
Hiding behind Converts.To is what I found in a comment from Tuna Tuksoz in this blog post. I’ll be honest with you I haven’t used the Type Descriptor before so I am not going to make a fool out of myself explaining it in detail but obviously it holds information about types and registers / gets converters for the types it knows about.
public static class Converts
{
public static T To<T>(object value)
{
return (T)To(typeof(T), value);
}
public static object To(Type t, object value)
{
TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}
public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
I would have named my class Convert but then I would have to use System.Convert in all other places. Maybe I should just switch to this generic one instead :)