Сериализовать свойство как атрибут Xml в элементе
У меня есть следующий класс:
[Serializable]
public class SomeModel
{
[XmlElement("SomeStringElementName")]
public string SomeString { get; set; }
[XmlElement("SomeInfoElementName")]
public int SomeInfo { get; set; }
}
Какой (при заполнении некоторыми тестовыми данными) и Сериализованный с помощью XmlSerializer.Serialize() приводит к следующему XML:
<SomeModel>
<SomeStringElementName>testData</SomeStringElementName>
<SomeInfoElementName>5</SomeInfoElementName>
</SomeModel>
Что мне нужно, так это:
<SomeModel>
<SomeStringElementName Value="testData" />
<SomeInfoElementName Value="5" />
</SomeModel>
Есть ли способ указать это как атрибуты без написания собственного кода сериализации?
Ответы
Ответ 1
Вам понадобятся классы-оболочки:
public class SomeIntInfo
{
[XmlAttribute]
public int Value { get; set; }
}
public class SomeStringInfo
{
[XmlAttribute]
public string Value { get; set; }
}
public class SomeModel
{
[XmlElement("SomeStringElementName")]
public SomeStringInfo SomeString { get; set; }
[XmlElement("SomeInfoElementName")]
public SomeIntInfo SomeInfo { get; set; }
}
или более общий подход, если вы предпочитаете:
public class SomeInfo<T>
{
[XmlAttribute]
public T Value { get; set; }
}
public class SomeModel
{
[XmlElement("SomeStringElementName")]
public SomeInfo<string> SomeString { get; set; }
[XmlElement("SomeInfoElementName")]
public SomeInfo<int> SomeInfo { get; set; }
}
И затем:
class Program
{
static void Main()
{
var model = new SomeModel
{
SomeString = new SomeInfo<string> { Value = "testData" },
SomeInfo = new SomeInfo<int> { Value = 5 }
};
var serializer = new XmlSerializer(model.GetType());
serializer.Serialize(Console.Out, model);
}
}
будет производить:
<?xml version="1.0" encoding="ibm850"?>
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SomeStringElementName Value="testData" />
<SomeInfoElementName Value="5" />
</SomeModel>
Ответ 2
Вроде, используйте XmlAttribute
вместо XmlElement
, но он не будет выглядеть так, как вы хотите. Он будет выглядеть следующим образом:
<SomeModel SomeStringElementName="testData">
</SomeModel>
Единственный способ, с помощью которого я могу достичь того, чего вы хотите (изначально), - это иметь свойства, указывающие на объекты с именем SomeStringElementName и SomeInfoElementName, где класс содержит один геттер с именем "значение". Вы можете сделать этот шаг дальше и использовать DataContractSerializer, чтобы классы-оболочки могли быть частными. XmlSerializer не будет читать частные свойства.
// TODO: make the class generic so that an int or string can be used.
[Serializable]
public class SerializationClass
{
public SerializationClass(string value)
{
this.Value = value;
}
[XmlAttribute("value")]
public string Value { get; }
}
[Serializable]
public class SomeModel
{
[XmlIgnore]
public string SomeString { get; set; }
[XmlIgnore]
public int SomeInfo { get; set; }
[XmlElement]
public SerializationClass SomeStringElementName
{
get { return new SerializationClass(this.SomeString); }
}
}