Представляя логическое значение как int для XMLSerialization в C#


Я работаю с XML-структуре, которая требует логических значений представлено в виде 1 или 0.

Итак, предположим, что вывод в формате XML должен выглядеть так:

<valid>1</valid>

Несколько узлов могут быть представлены таким образом, поэтому я сделал структуру, чтобы справиться с этим. Решение я нашел, работает, но не хватает шарма. Ок, нет, это не просто отсутствие шарма, это хреново.

(Реализуются в .Сеть 4)

public struct MyCrappyBool : IXmlSerializable
{
    private int _IntValue;
    private bool _BoolValue;

    public int IntValue
    {
        get { return _IntValue; }
        set
        {
            if (value < 0 || value > 1)
                throw new ArgumentOutOfRangeException();
            _IntValue = value;
            _BoolValue = value == 1;
        }
    }
    public bool BoolValue
    {
        get { return _BoolValue; }
        set
        {
            _BoolValue = value;
            _IntValue = value ? 1 : 0;
        }
    }

    public MyCrappyBool(int intValue) : this()
    {
        IntValue = intValue;
    }
    public MyCrappyBool(bool boolValue): this()
    {
        BoolValue = boolValue;
    }

    #region IXmlSerializable Members
    public XmlSchema GetSchema() { return null; }
    public void ReadXml(XmlReader reader)
    {
        IntValue = int.Parse(reader.ReadString());
    }
    public void WriteXml(XmlWriter writer)
    {
        writer.WriteString(IntValue.ToString());
    }
    #endregion
}

Это невероятно утомительно, в первую очередь, потому что мне нужно инстанцировать каждый раз:

MyCrappyBool isValid = new MyCrappyBool(true);

Но даже тогда, некоторые классные неявной перегрузки могут решать, что:

    public static implicit operator MyCrappyBool(bool boolValue)
    {
        return new MyCrappyBool(boolValue);
    }
    public static implicit operator MyCrappyBool(int intValue)
    {
        return new MyCrappyBool(intValue);
    }

Это все-таки много кода для одного... херовый логическое.

Позже, это может быть (в формате XML) сериализуется в рамках любого другого класса:

[XmlElement("valid")]
public MyCrappyBool IsValid { get; set; }
[XmlElement("active")]
public MyCrappyBool IsActive { get; set; }

Есть простой способ, об этом я не вижу?


Обновление: обратная неявная перегрузка оператора!

    public static implicit operator bool(MyCrappyBool myCrappyBool)
    {
        return myCrappyBool.BoolValue;
    }

    public static implicit operator int(MyCrappyBool myCrappyBool)
    {
        return myCrappyBool.IntValue;
    }

Это значит, что все свойства могут быть частными.



5372
5
задан 15 сентября 2011 в 01:09 Источник Поделиться
Комментарии
4 ответа

Я бы реализовать это так:

public struct Bit : IEquatable<Bit>, IXmlSerializable
{
private int value;
public Bit(bool value) { this.value = value ? 1 : 0; }
public Bit(int value) : this(value != 0) { }

public bool Equals(Bit other) { return this.value == other.value; }
public override bool Equals(object obj) { return obj is Bit && this.Equals((Bit)obj); }
public override int GetHashCode() { return value.GetHashCode(); }
public override string ToString() { return this.value.ToString(); }

public static implicit operator int(Bit value) { return value.value; }
public static explicit operator bool(Bit value) { return value.value != 0; }

System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() { throw new NotImplementedException(); }
void IXmlSerializable.ReadXml(XmlReader reader) { this.value = reader.ReadElementContentAsInt(); }
void IXmlSerializable.WriteXml(XmlWriter writer) { writer.WriteValue(this.value); }
}

Было бы лучше, чтобы хранить значение как целое число, так как это "истинное" значение, которое вас интересует. Это значение нормируется на C семантикой (т. е. значение false , если 0, правда, в противном случае в противовес верно , если 1, значение false в противном случае). Что будет чувствовать ко мне более естественным, но это до вас.

Я был бы осторожен с перегрузкой операторов. Не делай этого только потому, что вы можете, делаете это, потому что это имеет смысл. Я бы остановился на реализации операторов отливки из явного вида (так как это единственный способ получить по стоимости), использовать конструкторы в противном случае. И только один из них неявное преобразование, в противном случае вы столкнетесь с ошибками двусмысленности, если вы используете это много в коде.

Рассмотреть вопрос о выполнении интерфейс IEquatable интерфейс и прочие соответствующие изменения. Если вы намерены использовать его в своем коде, это может оказаться бесценным.

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

6
ответ дан 15 сентября 2011 в 08:09 Источник Поделиться

А теперь нечто совсем другое. При этом не имеет гибкости неявного преобразования в bool, и я думаю, что это следующая лучшая вещь:

public enum BoolEnum
{
[XmlEnum("0")]
False = 0,
[XmlEnum("1")]
True = 1
}

И... вот оно! Он сериализует BoolEnum.Правда , как "1", и может десериализовать от него тоже. Хотя ловить ошибки не существует,. Если значение в файле должны быть другими, чем 1 или 0, в исключение InvalidOperationException в другую бросается. Если есть способ, чтобы настроить это исключение, я хотел бы знать это.

3
ответ дан 17 сентября 2011 в 04:09 Источник Поделиться

Вот возможный ответ, хотя я не уверен, что она идет достаточно далеко для вас

public struct MyCrappyBool : IXmlSerializable
{
public bool Value
{
get; private set;
}

public MyCrappyBool(object v)
{
bool value = false;

if(Boolean.TryParse(v, out value))
Value = value;
else
throw new ArgumentException("Parameter not a valid boolean value");
}

#region IXmlSerializable Members
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
Value = int.Parse(reader.ReadString()) == 1;
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Value ? "1" : "0");
}
#endregion
}

Я бы ограничить тип элемента в XML указать все возможные значения в определения xsd. В противном случае я бы просто еще SetBoolean(int) метод, что через исключение, если значение не 0.

Я уверен, что есть и другие способы. Я не уверен, если система.В формате XML.Сериализации.Атрибут XmlElementAttribute уже сделала это для вас, но может быть стоит посмотреть.

1
ответ дан 15 сентября 2011 в 03:09 Источник Поделиться

На основе идей dreza, сейчас я уже: (и почему-то я вижу это лучше в качестве ответа, чем редактировать на вопрос):

public struct MyCrappyBool : IXmlSerializable
{
private bool Value;

public MyCrappyBool(int intValue) : this(intValue == 1)
{ }
public MyCrappyBool(bool boolValue) : this()
{
Value = boolValue;
}

public override string ToString()
{
//return ((int)this).ToString();
return Value ? "1" : "0";
}

public static implicit operator MyCrappyBool(bool boolValue)
{
return new MyCrappyBool(boolValue);
}
public static implicit operator MyCrappyBool(int intValue)
{
return new MyCrappyBool(intValue);
}
public static implicit operator bool(MyCrappyBool myCrappyBool)
{
return myCrappyBool.Value;
}
public static implicit operator int(MyCrappyBool myCrappyBool)
{
return myCrappyBool ? 1 : 0;
}

#region IXmlSerializable Members
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
Value = int.Parse(reader.ReadString()) == 1;
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(ToString());
}
#endregion
}

Если честно, ((инт)этого).Метод toString() кажется запутанным и зла.

0
ответ дан 15 сентября 2011 в 03:09 Источник Поделиться