Как я могу заставить XmlSerializer кодировать bools да/нет?

Эта функция проверяет, содержит ли List parent Список target, используя некоторые LINQ:

    public static bool ContainsSequence<T>(this List<T> parent, List<T> target)
    {
        for (int fromElement = parent.IndexOf(target.First());
            (fromElement != -1) && (fromElement <= parent.Count - target.Count);
            fromElement = parent.FindIndex(fromElement + 1, p => p.Equals(target.First())))
        {
            var comparedSequence = parent.Skip(fromElement).Take(target.Count);
            if (comparedSequence.SequenceEqual(target)) return true;
        }
        return false;
    }       
15
задан Blorgbeard 9 March 2009 в 05:14
поделиться

5 ответов

Хорошо, я изучал это еще немного. Вот то, что я придумал:

// use this instead of a bool, and it will serialize to "yes" or "no"
// minimal example, not very robust
public struct YesNo : IXmlSerializable {

    // we're just wrapping a bool
    private bool Value;

    // allow implicit casts to/from bool
    public static implicit operator bool(YesNo yn) {
        return yn.Value;
    }
    public static implicit operator YesNo(bool b) {
        return new YesNo() {Value = b};
    }

    // implement IXmlSerializable
    public XmlSchema GetSchema() { return null; }
    public void ReadXml(XmlReader reader) {
        Value = (reader.ReadElementContentAsString() == "yes");
    }
    public void WriteXml(XmlWriter writer) {
        writer.WriteString((Value) ? "yes" : "no");
    }
}

Тогда я изменяю свой класс Foo на это:

[XmlRoot()]
public class Foo {      
    public YesNo Bar { get; set; }
}

Примечание, что, потому что YesNo неявно castable к bool (и наоборот), можно все еще сделать это:

Foo foo = new Foo() { Bar = true; };
if ( foo.Bar ) {
   // ... etc

, Другими словами, можно рассматривать его как bool.

И w00t! Это сериализирует к этому:

<Foo><Bar>yes</Bar></Foo>

Это также десериализовывает правильно.

существует, вероятно, некоторый способ заставить мой XmlSerializer автоматически бросать любой bool с, с которой он встречается к YesNo с, когда он идет - но я еще не нашел его. Кто-либо?

22
ответ дан 1 December 2019 в 01:53
поделиться

Очень простой. Используйте суррогатное свойство. Примените XmlIgnore на фактическое свойство. Суррогат является строкой и должен использовать атрибут XmlElement, который берет переопределение имени элемента. Определите название фактическое свойство в переопределении. Суррогатное свойство сериализирует по-другому на основе значения фактического свойства. Необходимо также обеспечить метод set для Суррогата, и метод set должен установить фактическое свойство соответственно для любого значения, которое это сериализировало. Другими словами, это должно пойти обоими путями.

Надрез:

    public class SomeType 
    {

        [XmlElement]
        public int IntValue;

        [XmlIgnore]
        public bool Value;

        [XmlElement("Value")]
        public string Value_Surrogate {
            get { return (Value)? "Yes, definitely!":"Absolutely NOT!"; }
            set { Value= (value=="Yes, definitely!"); }
        }

    }

щелкают здесь для полный компилируемый исходный пример .

8
ответ дан 1 December 2019 в 01:53
поделиться

То, чтобы заставлять значение bool сериализировать как "да" или "нет" изменяет тип данных от того, чтобы быть булевской переменной вообще. Вместо этого можно ли добавить раздельное имущество, которое оценивает булевскую переменную и возвращает "да" или "нет" как соответствующие, поскольку это - тип данных? Возможно, Вы могли даже вызвать "да" или "нет", заставив тип возврата быть перечислением, которое только определяет те значения.

public YesOrNo DoYouLoveIt
{
    get { return boolToEvaluate ? YesOrNo.Yes : YesOrNo.No; }
}

, Который мог бы быть излишеством, но мог бы ответить на Вашу потребность. Единственная причина я поднимаю перечисление для такого простого значения, Вы ограничили бы значения по сравнению с разрешением любой строки.

3
ответ дан 1 December 2019 в 01:53
поделиться

Вашим примером свойства является, вероятно, самый простой способ, которым Вы могли сделать это. Если это помогает, я полагаю, что Вы не должны делать это общественной собственностью, так как атрибут реализует ISerializable на классе за Вашей спиной. Для включения десериализации необходимо быть в состоянии просто реализовать set { Bar = value == "yes"; }

0
ответ дан 1 December 2019 в 01:53
поделиться

То, что необходимо сделать, больше походит на проблему дисплея. Если Ваше приложение позволит, то Вы будете более обеспеченным хранением типа данных как булевская переменная и отображение Да/Нет в Вашем пользовательском интерфейсе.

-2
ответ дан 1 December 2019 в 01:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: