Now, why does XmlNode.SelectNodes(string xpath) return null if it doesn’t find anything?
I have some existing code that reads some parameters from XML, and passes some objects and those parameters into a method that filters those objects into two sets – one that is sensitive in some way to those parameters, and one that’s not.
FilterProducts(
XmlNodeList processes,
XmlNodeList processAttributes,
out List<Product> sensitiveFolio,
out List<Product> nonSensitiveFolio);
I’m drawing the list of processes and processAttributes from XML – and in some cases people don’t define any attributes, wanting to just build a folio sensitive to a list of processes. In this case the XmlNodeList returned is null – and when I pass that to FilterProducts it blows up.
After the null pattern, then, I figured what I wanted to do was actually pass an empty XmlNodeList rather than a null. FilterProducts could then just pass over the attributes, and work out what was dependent on the processes only. Then I realised that what I really needed to do was dig through FilterProducts and refactor it because it was doing too much – at least compared to the usage pattern was now different to that which originally formed it.
However; both these can happen in sequence. I could deliver the simpler – using the existing code and an empty list, which wouldn’t affect any other code, then taking a look at refactoring FilterProducts, which might affect other parts of the codebase. So, populate processAttributes with a successully parsed XmlNodeList, or a new EmptyNodeList if that's null:
XmlNodeList processAttributes =
myConfigNode.SelectNodes("/processAttributes") ?? new EmptyNodeList;
and then defined EmptyNodeList by subclassing XmlNodeList:
private class EmptyNodeList : XmlNodeList
{
public override XmlNode Item(int index)
{
throw new NotImplementedException();
}
public override IEnumerator GetEnumerator()
{
return new EmptyNodeListEnumerator();
}
public class EmptyNodeListEnumerator : IEnumerator
{
public bool MoveNext()
{
return false;
}
public void Reset()
{
throw new NotImplementedException();
}
public object Current
{
get
{
throw new NotImplementedException();
}
}
}
public override int Count
{
get
{
return 0;
}
}
}
That works fine, delivering some code, and leaving a look at refactoring some code used in multiple places for later.
2 comments:
could it be static class?
Not for this use case -- you can't instantiate a static class.
Post a Comment