patterncsharpMinor
Presenting a boolean as an int for XMLSerialization in C#
Viewed 0 times
booleanxmlserializationpresentingforint
Problem
I'm working with an XML structure that requires booleans to be represented as 1 or 0.
So, suppose the XML output has to look like:
Several nodes can be represented this way, so I made a struct to handle this. The solution I found works, but lacks oomph. OK, no, it doesn't just lack oomph, it sucks.
(Implemented in .NET 4)
This is incredibly tedious, first and foremost because I need to instantiate every time:
But even then, some nifty implicit overloading can address that:
That's still a lot of code for one... crappy boolean.
Later, it can be (XML) serialized as part of any other class:
```
[XmlElement("valid")]
public MyCrappyBool IsV
So, suppose the XML output has to look like:
1Several nodes can be represented this way, so I made a struct to handle this. The solution I found works, but lacks oomph. OK, no, it doesn't just lack oomph, it sucks.
(Implemented in .NET 4)
public struct MyCrappyBool : IXmlSerializable
{
private int _IntValue;
private bool _BoolValue;
public int IntValue
{
get { return _IntValue; }
set
{
if (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
}This is incredibly tedious, first and foremost because I need to instantiate every time:
MyCrappyBool isValid = new MyCrappyBool(true);But even then, some nifty implicit overloading can address that:
public static implicit operator MyCrappyBool(bool boolValue)
{
return new MyCrappyBool(boolValue);
}
public static implicit operator MyCrappyBool(int intValue)
{
return new MyCrappyBool(intValue);
}That's still a lot of code for one... crappy boolean.
Later, it can be (XML) serialized as part of any other class:
```
[XmlElement("valid")]
public MyCrappyBool IsV
Solution
I'd implement it like this:
It would be better to store your value as an integer as that is the "true" value that you're interested in. It's value is normalized using C semantics (i.e.,
I'd be careful with the operator overloading. Don't do it just because you can, do it because it makes sense. I'd stop at implementing casting operators from the type explicitly (since that's the only way to get at the value), use the constructors otherwise. And make only one of them an implicit cast, otherwise you will run into ambiguity errors if you use this a lot in your code.
Consider implementing the
Consider implementing the
public struct Bit : IEquatable, 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); }
}It would be better to store your value as an integer as that is the "true" value that you're interested in. It's value is normalized using C semantics (i.e.,
false if 0, true otherwise as opposed to true if 1, false otherwise). That would feel more natural to me but it's up to you.I'd be careful with the operator overloading. Don't do it just because you can, do it because it makes sense. I'd stop at implementing casting operators from the type explicitly (since that's the only way to get at the value), use the constructors otherwise. And make only one of them an implicit cast, otherwise you will run into ambiguity errors if you use this a lot in your code.
Consider implementing the
IEquatable interface and other appropriate overrides. If you intend to use this in your code, this could be invaluable.Consider implementing the
IXmlSerializable interface explicitly. If you intend to use this type as you would any other in your code, you probably wouldn't want to see the serialization methods all the time. Otherwise if you are only using this for serialization, implement it implicitly.Code Snippets
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); }
}Context
StackExchange Code Review Q#4829, answer score: 6
Revisions (0)
No revisions yet.