Сериализовать свойство строки как атрибут, даже если строка пуста

public class Hat
{
    [XmlTextAttribute]
    public string Name { get; set; }
    [XmlAttribute("Color")]
    public string Color { get; set; }
}

var hat1 = new Hat {Name="Cool Hat", Color="Red"};
var hat2 = new Hat {Name="Funky Hat", Color=null};

Это то, что я получаю (обратите внимание на отсутствующий атрибут цвета на Funky Hat):

<Hats>
 <Hat Color="Red">Cool Hat</Hat>
 <Hat>Funky Hat</Hat>
</Hats>

Это то, что я хочу:

<Hats>
 <Hat Color="Red">Cool Hat</Hat>
 <Hat Color="">Funky Hat</Hat>
</Hats>

Как я могу заставить сериализатор создать пустой атрибут вместо того, чтобы его оставить?

EDIT:

Оказывается, я идиот и создал пример, содержащий ошибку, потому что я хотел упростить код для примера.

Если значение цвета равно "" (или string.empty), оно фактически сериализуется как пустой атрибут. Тем не менее, у меня действительно было пустое значение, а не пустая строка, поэтому она была опущена.

Таким образом, поведение, которое я хотел, на самом деле было уже поведением примера, который я создал.

Извините, ребята!

Ответы

Ответ 1

Попробуйте использовать List<Hat> в качестве контейнера. Используя это:

var hats = new List<Hat>
    {
        new Hat { Name = "Cool Hat", Color = "Red" }, 
        new Hat { Name = "Funky Hat", Color = string.Empty }
    };

using (var stream = new FileStream("test.txt", FileMode.Truncate))
{
    var serializer = new XmlSerializer(typeof(List<Hat>));
    serializer.Serialize(stream, hats);
}

Я получаю это:

<?xml version="1.0"?>
<ArrayOfHat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Hat Color="Red">Cool Hat</Hat>
  <Hat Color="">Funky Hat</Hat>
</ArrayOfHat>

Ответ 2

Вы можете попробовать установить для свойства Specified значение true. Кроме того, я считаю, что вы можете использовать свойство ## Specified для управления сериализацией, например:

[XmlAttribute("Color")]
public string Color { get; set; }
[XmlIgnore]
public bool ColorSpecified { get { return true; } }    // will always serialize

Или вы можете сериализовать, если он не равен null:

[XmlIgnore]
public bool ColorSpecified { get { return this.Color != null; } }

Ответ 3

Есть два способа сделать это.

Вы можете использовать [XmlElement(IsNullable=true)], который заставит нулевое значение распознаваться.

Вы также можете использовать String.Empty вместо "". Это распознается как пустая строка, а не нуль.