I have a class what takes care of reading and holding the XML file. Right now a simple version of it looks like this:
public class EstEIDPersoConfig
{
public bool LaunchDebugger { get ; set; }
public string Password { get; set; }
public int Slot { get; set; }
public string Reader { get; set; }
public string TestInput { get; set; }
public bool Logging { get; set; }
public EstEIDPersoConfig()
{
XElement xml = XElement.Load(myxml.xml);
XElement Configuration = xml.Element("Configuration");
LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value);
Password = Configuration.Element("Password").Value;
Slot = Convert.ToInt32(Configuration.Element("Slot").Value);
Reader = Configuration.Element("Reader").Value;
TestInput = Configuration.Element("TestInput").Value;
Logging = Convert.ToBoolean(Configuration.Element("Logging").Value);
}
}
And there will be more later. so the problem is that if some element does not exist in xml i get System.NullReferenceException
. So i need to check if the element is null
or not. Heres one way to do this:
var value = Configuration.Element("LaunchDebugger").Value;
if (value != null)
LaunchDebugger = Convert.ToBoolean(value);
else
throw new Exception("LaunchDebugger element missing from xml!");
But doing that for every element would be just too much. So i need some good ideas how to simplify this system so it wouldn't end up in 1000 lines of code.
EDIT: Edited the last code snippet, the idea was not to set a default value, idea was to notify the user that this element whats null is missing from the xml.
The idea here comes directly from abatischev's answer so he deserves the credit.
As perscribed by Microsoft here you can just cast the XElement
to the type you desire.
LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger");
if you want to handle the null
case I guess you could do
LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true);
or perhaps
LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false);
depending on your business logic. If you do the same coalescene for a specific type it may be appropriate to wrap this one liner in a method, extension or otherwise but I'm uncertain it would add much.
(bool)Configuration.Element("LaunchDebugger")
or
(bool?)Configuration.Element("LaunchDebugger")
should not throw exception.
See MSDN:
Boolean
)Nullable<Boolean>
)I have an extension method that I use for just this kind of thing:
public static T GetValue<T>(
this XElement @this,
XName name,
Func<XElement, T> cast,
Func<T> @default)
{
var e = @this.Element(name);
return (e != null) ? cast(e) : @default();
}
It gives you the casting required and also a default value factory.
Here's how you'd use it:
LaunchDebugger = Configuration.GetValue("LaunchDebugger",
x => Convert.ToBoolean(x), () => false);
Password = Configuration.GetValue("CMKPassword", x => (string)x, () => "");
Slot = Configuration.GetValue("CMKSlot", x => (int)x, () => -1);
Reader = Configuration.GetValue("Reader", x => (string)x, () => "");
TestInput = Configuration.GetValue("TestInput", x => (string)x, () => "");
Logging = Configuration.GetValue("Logging",
x => Convert.ToBoolean(x), () => false);
Extract the logic to a method and have overloaded methods for Int32,boolean and other data types conversion.
public static void GetElementValue(XElement xElement, string parameter, out bool value)
{
var stringValue = xElement.Element(parameter).Value;
value = false;
if (value != null)
value = Convert.ToBoolean(stringValue);
}
You can define a method to extract the value for you and do some checking on null there. So wrap the value retrieval in your own method like so:
public string GetXMLValue(XElement config, string elementName){
var element = Configuration.Element(elementName);
if(element == null)
return String.Empty;
return element.Value;
}
Of course you can extend this to work correctly with parsing to boolean etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With