Проверьте, является ли XElement нулевым глобально - PullRequest
5 голосов
/ 26 октября 2011

У меня есть класс, который занимается чтением и хранением файла XML. Прямо сейчас простая версия выглядит так:

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);
     }
 }

И будет еще позже. так что проблема в том, что если какой-то элемент не существует в XML, я получаю System.NullReferenceException. Поэтому мне нужно проверить, является ли элемент null или нет. Вот один из способов сделать это:

var value = Configuration.Element("LaunchDebugger").Value;
if (value != null)
    LaunchDebugger = Convert.ToBoolean(value);
else
    throw new Exception("LaunchDebugger element missing from xml!");

Но делать это для каждого элемента было бы слишком много. Поэтому мне нужны хорошие идеи, как упростить эту систему, чтобы она не заканчивалась 1000 строками кода.

РЕДАКТИРОВАТЬ: отредактировал последний фрагмент кода, идея не состояла в том, чтобы установить значение по умолчанию, идея состояла в том, чтобы уведомить пользователя, что этот элемент отсутствует в xml.

Ответы [ 6 ]

4 голосов
/ 26 октября 2011

Идея здесь исходит непосредственно из ответа Абатищева, поэтому он заслуживает похвалы.

Как предписано Microsoft здесь , вы можете просто привести XElement к желаемому вами типу.

LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger");

если вы хотите заняться делом null, я думаю, вы могли бы сделать

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true);

или, возможно,

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false);

в зависимости от вашей бизнес-логики. Если вы делаете ту же самую коалесцену для определенного типа, может быть целесообразно обернуть этот один вкладыш в метод, расширение или иным образом, но я не уверен, что это добавит многое.

4 голосов
/ 26 октября 2011
(bool)Configuration.Element("LaunchDebugger")

или

(bool?)Configuration.Element("LaunchDebugger")

не должно выбрасывать исключение.

См. MSDN:

2 голосов
/ 26 октября 2011

У меня есть метод расширения, который я использую только для такого рода вещей:

    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();
    }

Он дает вам необходимый кастинг и фабрику значений по умолчанию.

Вот как выбуду использовать его:

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);
2 голосов
/ 26 октября 2011

Извлечение логики в метод и перегруженные методы для преобразования Int32, логических и других типов данных.

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);
    }
1 голос
/ 26 октября 2011

Вы можете определить метод для извлечения значения для вас и сделать некоторую проверку на ноль там.Оберните поиск значения в свой собственный метод следующим образом:

public string GetXMLValue(XElement config, string elementName){
    var element = Configuration.Element(elementName);

    if(element == null)
        return String.Empty;

    return element.Value;
}

Конечно, вы можете расширить это для правильной работы с синтаксическим анализом до логического значения и т. Д.

1 голос
/ 26 октября 2011

Как насчет внешнего метода:

public static class XElementExtensions
{
    public static bool AsBoolean(this XElement self, bool defaultValue)
    {
        if (self == null)
        {
            return defaultValue;
        }
        if (!string.IsNullOrEmpty(self.Value))
        {           
            try
            {
                return XmlConvert.ToBoolean(self.Value);
            }
            catch
            {
                return defaultValue;
            }
        }
        return defaultValue;
    }
}

Я проверял это с помощью SnippetCompiler:

XElement test = new XElement("test", 
    new XElement("child1"),
    new XElement("child2", new XText("true")),
    new XElement("child3", new XText("false")),
    new XElement("child4", new XText("rubbish")));

WL(test.Element("child1").AsBoolean(false)); // note, "child1" has no value (or is `""`)
WL(test.Element("child2").AsBoolean(false));
WL(test.Element("child3").AsBoolean(false));
WL(test.Element("child4").AsBoolean(false));
WL(test.Element("child5").AsBoolean(false)); // note, "child5" doesn't exist        

Чтобы получить этот результат:

False
True
False
False
False

Добавьте больше таких методов для других типов, а также добавьте AsBoolean(defaultValue), так как это может пригодиться, когда вы хотите по умолчанию true!

Как уже говорили другие, вы можете использовать оператор ??, чтобы задать значение для null. Это не гнездится, однако, так:

LaunchDebugger = XmlConvert.ToBoolean(Configuration.Element("LaunchDebugger").Value) ?? false;

будет через NullReferenceException, если в XML-файле нет такого элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...