Сериализуемый класс с динамическим набором полей
Дайте наводку как реализовать класс который можно будет сериализовать в такой XML:
<mcbmsg>
<head>
<ServiceName>SED</ServiceName>
<RequestUID/>e6e9af2a-686e-0a88-9c22-0cc2b5250be8</RequestUID>
<ReplyUID/>
<ReferenceUID/>
<RequestDT>2022-07-21T12:12:12</RequestDT>
<Sender>IBSO</Sender>
<Receiver>TESSA</Receiver>
</head>
<body>
<CardID>13C85CBF-320A-4C1A-89EE-31119ED564EF</CardID>
<IsAccepted>1</IsAccepted>
</body>
</mcbmsg>
Проблема лишь в том что состав полей body постоянно меняется. т.е. секция head не меняется, а начинка body может быть разная.
пробовал реализовать через Idictionary но выдает ошибку при сериализации
namespace Shared.Model.Integration
{
[XmlRoot(ElementName = "head")]
public class Head
{
[XmlElement(ElementName = "ServiceName")]
public string ServiceName { get; set; }
[XmlElement(ElementName = "RequestUID")]
public string RequestUID { get; set; }
[XmlElement(ElementName = "ReplyUID")]
public string ReplyUID { get; set; }
[XmlElement(ElementName = "ReferenceUID")]
public string ReferenceUID { get; set; }
[XmlElement(ElementName = "RequestDT")]
public string RequestDT { get; set; }
[XmlElement(ElementName = "Sender")]
public string Sender { get; set; }
[XmlElement(ElementName = "Receiver")]
public string Receiver { get; set; }
}
[XmlRoot(ElementName = "Body")]
public class Body
{
[XmlElement(ElementName = "Fields")]
public Dictionary<string, object> Fields { get; set; }
}
[XmlRoot(ElementName = "Msg")]
public class Msg
{
[XmlElement(ElementName = "head")]
public Head Head { get; set; }
[XmlElement(ElementName = "body")]
public Body Body { get; set; }
}
}
помогите с реализацией body плз.
Ответы (1 шт):
Задачу можно решить по-разному.
Создаём класс со всем набором возможных свойств. Навешиваем на эти свойства атрибут System.ComponentModel.DefaultValue. И задаём там значение по умолчанию, которое не будет сериализоваться.
У ссылочных типов дефолтное значение null.
using System.ComponentModel;
public class Body
{
public string CardID { get; set; }
[DefaultValue(0)]
public int IsAccepted { get; set; }
[DefaultValue(0)]
public int X { get; set; }
[DefaultValue(0)]
public int Y { get; set; }
}
Если задано:
Body = new Body
{
CardID = "13C85CBF-320A-4C1A-89EE-31119ED564EF",
IsAccepted = 1,
// свойства X и Y равны дефолтному значению (0)
// поэтому в XML их не будет
}
Результат будет:
<body>
<CardID>13C85CBF-320A-4C1A-89EE-31119ED564EF</CardID>
<IsAccepted>1</IsAccepted>
</body>
Если задано:
Body = new Body
{
X = 3,
Y = 4
}
Результат будет:
<body>
<X>3</X>
<Y>4</Y>
</body
Другой вариант - использовать свойства с суффиксом Specified.
XmlSerializer учитывает значение этих свойств в процессе работы. Если оно задано true - свойство с совпадающим именем будет сериализовано, иначе - нет.
Сами такие свойства помечаем атрибутом XmlIgnore.
public class Body
{
public string CardID { get; set; }
public int IsAccepted { get; set; }
public int X { get; set; }
public int Y { get; set; }
[XmlIgnore]
public bool CardIDSpecified { get; set; }
[XmlIgnore]
public bool IsAcceptedSpecified { get; set; }
[XmlIgnore]
public bool XSpecified { get; set; }
[XmlIgnore]
public bool YSpecified { get; set; }
}
Задавая эти свойства можно гибко настраивать список сериализуемых значений:
var body = new Body();
//...
body.CardIDSpecified = false;
body.IsAcceptedSpecified = false;
body.XSpecified = true;
body.YSpecified = true;
P.S. Также можно использовать методы с префиксом ShouldSerialize