Как проверить состояние xml-значения?

#c# #xml #linq-to-xml

Вопрос:

У меня есть два правила, которые я хочу реализовать в XML-приложении.

1 Если вес больше 10, то по названию Отдела должно быть написано: Большой

Комментарии:

1. Почему бы вам не проверить свойства, соответствуют ли они условию, и если да, то добавить маркер строки отдела в строку результата? Это не сложная проблема.

2. Вы даже можете встроить условную проверку.

3. Да, но для этого будет чище использовать некоторые шаблоны. Но я застрял здесь.

Ответ №1:

Лучше всего позволить самому Department свойству вычислить его значение (вычисляемое свойство). Это чище и удобочитаемее, так как вычисления выполняются там, где вы этого ожидаете. В противном случае в сценарии, где вычисления зависят более чем от одного свойства, вы обнаружите, что пишете дублированный вычислительный код в каждом участвующем свойстве.
Поэтому выполняйте вычисление при запросе значения, то есть при вызове вычисляемого свойства Get() , а не при изменении участвующих свойств. Если вычисления более сложные, то следование этим правилам также повысит производительность.

Также избегайте реализации такого фильтра непосредственно в Set() / Get() свойства. Переместите его в метод.

Я также предлагаю использовать оператор переключения или выражение переключения, поскольку это более читабельно, чем длинная цепочка блоков if-else, и, следовательно, проще в обслуживании. При использовании C# 9 выражение переключения может быть мощным инструментом фильтрации с хорошо читаемым синтаксисом.

Кроме того, поскольку строка, которую вы пытаетесь создать для печати, является фиксированным string представлением фактического Parcel экземпляра, было бы более уместно переопределить Parcel.ToString .

Ваш класс посылок должен выглядеть примерно так:

Посылка.cs

 public class Parcel
{
  public override string ToString() 
    => $"Name: {this.Name} - Postal code {this.PostalCode} - Weight {this.Weight} - Value {this.Value} - Department {this.Department}";

  public string Name { get; set; }
  public string PostalCode { get; set; }
  public decimal Weight { get; set; }
  public decimal Value { get; set; }
  public string Department => CreateDepartmentValue();

  private string CreateDepartmentValue()
  {
    var result = string.Empty;

    switch (this.Weight)
    {
      case decimal weightInKiloGrams when weightInKiloGrams <= 1: result = "Mail"; break;
      case decimal weightInKiloGrams when weightInKiloGrams <= 10: result = "Regular"; break;
      case decimal weightInKiloGrams when weightInKiloGrams > 10: result = "Heavy"; break;
    };


    switch (this.Value)
    {
      case decimal value when value > 1000: result  = ", Insurance"; break;
    };

    return resu<
  }
}
 

Пример Использования

 public class Program
{
  static void Main(string[] args)
  {

    XDocument xdoc = XDocument.Load($"Container.xml");
    var items = ...;

    foreach (var item in items)
    {
      // Call ToString() implicitly
      Console.WriteLine(item);
      Console.WriteLine("*********************************************************************");
    }

    Console.ReadLine();
  }
}
 

Ответ №2:

Вы можете создать посылку класса и определить отдел на основе веса и значения из вызова функции

 public class Parcel
{
    public string Name { get; set; }
    public string PostalCode { get; set; }
    public decimal Weight { get; set; }
    public decimal Value { get; set; }
    public string Department => GetDepartment();
    private string GetDepartment()
    {
        string _department = "";
        if (this.Weight <= 1)
        {
            _department = "Mail";
        }
        else if (this.Weight > 1 amp;amp; this.Weight <= 10)
        {
            _department = "Regular";
        }
        else if (this.Weight > 10)
        {
            _department = "Heavy";
        }
        else
        {
            _department = "Unknown";
        }

        if (this.Value > 1000)
        {
            _department  = ",Insurance";
        }

        return _department;
    }
}
 

Ваш XDcoument будет выглядеть так, как показано ниже

 XDocument xdoc = XDocument.Load($"XMLFile1.xml");

var items = xdoc.Descendants("Parcel")
                .Select(xelem => new Parcel
                {
                    Name = xelem.Element("Sender").Element("Name").Value,
                    PostalCode = xelem.Element("Sender").Element("Address").Element("PostalCode").Value,
                    Weight = Convert.ToDecimal(xelem.Element("Weight").Value),
                    Value = Convert.ToDecimal(xelem.Element("Value").Value)
                });

foreach (var item in items)
{
    Console.WriteLine($"{ item.Name} - { item.PostalCode} - { item.Weight} - { item.Value} - { item.Department}");
}
 

Выход

 Klaas - 2402AE - 0.02 - 0.0 - Mail
ykken groot B.V. - 2497GA - 2.0 - 0.0 - Regular
seti - 2497GA - 100.0 - 2000.0 - Heavy,Insurance
Aad - 2353HS - 11 - 500 - Heavy
 

Комментарии:

1. Привет, спасибо. Но если я хочу добавить еще одно условие, например: Отдел = Преобразовать. ToDecimal(xelem. Элемент(«Вес»). Значение) «Почта» : Конвертировать. ToDecimal(xelem. Элемент(«Вес»). Значение) > 1000 ? «Большой» : Преобразование. ToDecimal(xelem. Элемент(«Вес»). Значение) > 10 ? «Большой» : «Маленький» }); тогда это не работает

2. Тогда я не вижу почты с именем

3. @mightycodeNewton, я обновил пост более эффективным способом

4. Привет, Кришна, спасибо тебе. Я обновил сообщение. Не могли бы вы взглянуть на него в последний раз? Я также изменил кое-какой код. Спасибо

5. Да, в первой посылке вывода указано 2. Но значение в xml равно 0,02

Ответ №3:

Почему бы не расширить класс посылок, чтобы иметь свойство «DepartmentSize», которое обрабатывает размер:

 class Parcel
{
     public string DepartmentSize 
     {
         var parts = new List<string>();
         if(_Weight> 10)
             parts.Append("Big");
         if(_Value > 1000) 
             parts.Append("Large");
         return string.Join(",", parts);
     }
 }
 

Затем вы можете вывести размер следующим образом:

 Console.WriteLine($"... Department: {item.DepartmentSize}");
 

Комментарии:

1. Спасибо. Но как это связано? Я имею в виду, что посылка класса в данный момент не используется

2. Вы правы, ваш класс посылок не используется. Я так и думал. Тем не менее, в вашей программе вместо создания анонимного типа, почему бы не создать коллекцию посылок (с помощью конструктора), тогда мое решение будет работать.

3. Вы имеете в виду торговца парцеллами?