Каждый из ваших <MealPeriodx>
элементов состоит из смешанного содержимого и может содержать:
- Строковое значение;
- Последовательность
<Interval>
elements; - A
<Totals>
element.
Опираясь на ответ на Правильная сериализация XML и десериализация «смешанных» типов в .NET by Stefan , вы можете привязать такой элемент к типу ac # следующим образом:
public class MealPeriod
{
// A polymorphic array of "mixed" types.
// See /2014532/pravilnaya-xml-serializatsiya-i-deserializatsiya-smeshannyh-tipov-v-net
// and the solution by Stefan, https://stackoverflow.com/users/307747/stefan
// for why this works.
[XmlElement("Interval", typeof(Interval))]
[XmlElement("Totals", typeof(Totals))]
[XmlText(typeof(string))]
public List<object> Items { get; set; }
}
public class Interval
{
public string Name { get; set; }
public int Checks { get; set; }
public int Guests { get; set; }
public string AvgCheck { get; set; }
public string AvgGuest { get; set; }
public string Sales { get; set; }
}
public class Totals
{
public int Checks { get; set; }
public int Guests { get; set; }
public string AvgCheck { get; set; }
public string AvgGuest { get; set; }
public string Sales { get; set; }
}
Затем вы можете определить корневой объект SalesSummary
следующим образом, где каждыйMealPeriodx
свойство должно быть коллекцией MealPeriod
объектов, так как каждый <MealPeriodx>
появляется несколько раз в исходном XML:
public class SalesSummary
{
[XmlElement("MealPeriod1")]
public List<MealPeriod> MealPeriod1 { get; set; }
[XmlElement("MealPeriod1Sales")]
public decimal MealPeriod1Sales { get; set; }
[XmlElement("MealPeriod2")]
public List<MealPeriod> MealPeriod2 { get; set; }
[XmlElement("MealPeriod2Sales")]
public decimal MealPeriod2Sales { get; set; }
[XmlElement("MealPeriod3")]
public List<MealPeriod> MealPeriod3 { get; set; }
[XmlElement("MealPeriod3Sales")]
public decimal MealPeriod3Sales { get; set; }
[XmlElement("MealPeriod4")]
public List<MealPeriod> MealPeriod4 { get; set; }
[XmlElement("MealPeriod4Sales")]
public decimal MealPeriod4Sales { get; set; }
}
public static class MealPeriodExtensions
{
public static string MealPeriodName(this IEnumerable<MealPeriod> mealPeriods)
{
if (mealPeriods == null)
return null;
return String.Concat(mealPeriods.Where(m => m.Items != null).SelectMany(m => m.Items).OfType<string>());
}
public static IEnumerable<T> MealPeriodItems<T>(this IEnumerable<MealPeriod> mealPeriods)
{
if (mealPeriods == null)
return Enumerable.Empty<T>();
return mealPeriods.Where(m => m.Items != null).SelectMany(m => m.Items).OfType<T>();
}
}
Затем, с учетом вспомогательного метода десериализации, такогокак
public static class XmlSerializationHelper
{
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
{
serial = serial ?? new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlString))
{
return (T)serial.Deserialize(reader);
}
}
}
Вы можете сделать:
var summary = xml.LoadFromXml<SalesSummary>();
// Prints:
// MealPeriod1 name: "Lunch"
Console.WriteLine("MealPeriod1 name: \"{0}\"", summary.MealPeriod1.MealPeriodName());
// Prints
// MealPeriod1 Total Sales: "$6,447.58"
Console.WriteLine("MealPeriod1 Total Sales: \"{0}\"", summary.MealPeriod1.MealPeriodItems<Totals>().Single().Sales);
Примечания:
Если вы повторно сериализуете SalesSummary
в XML, тогдадва <MealPeriodx>
элемента будут смещены, чтобы стать смежными друг с другом.Нет простого способа избежать этого, используя XmlSerializer
, кроме , реализующего IXmlSerializable
или вручную создающего суррогатный массив [XmlAnyElement]
, как показано в этого ответа .
К счастью, ваш вопрос требует только десериализации.
Interval
и Totals
имеют много общих свойств, поэтому вы можете захотеть, чтобы они имели общий базовый класс или интерфейс.
Пример рабочей .Net скрипки здесь .