[quoted text, click to view] "Diego Mijelshon" <no@thanks.com> wrote in message news:%23GpCRnEGFHA.2692@TK2MSFTNGP10.phx.gbl...
> While the XmlSerializer can read boolean values as either 0/1 or true/false,
> it always writes true/false, which is a problem when I want to insert in an
> SQL Server bit column.
One cleaner way is to subclass an XmlWriter to replace "true" and "false"
literals with "1" and "0", respectively. When you think about it, examining
every string you write out to XML to see if it's "true" or "false" isn't the
most desirable accomplishment in the world; but this does relieve you as
the developer from having to create (many?) surrogate properties purely
for serialization purposes.
- - - BoolXmlTextWriter.cs
using System;
using System.IO;
using System.Xml;
public class BoolXmlTextWriter : XmlTextWriter
{
private delegate void WriterMethod( string text);
private WriterMethod _writeRaw;
private WriterMethod _writeString;
public BoolXmlTextWriter(TextWriter sink) : base( sink)
{
this._writeRaw = new WriterMethod(base.WriteRaw);
this._writeString = new WriterMethod(base.WriteString);
}
private void Write(string text, WriterMethod funcWriter)
{
int len = text.Length;
// Most text isn't "true" or "false" so before I do a char-by-char comparison on
// every string crossing my desk, reduce the number of candidates by throwing
// out (delegating to my base writer method) everything that's not 4 or 5-chars
// long.
//
if ((len == 4) || (len == 5))
{
// Most text also won't start with "t" or "f" so before I do a char-by-char
// comparison, throw out (delegate to my base writer method) everything
// that doesn't start with these characters.
//
char firstChar = text[0];
switch (firstChar)
{
case 't':
// Replace "true" with "1" (my apologies to 4- and 5-char long strings
// that actually begin with 't').
//
if (text == "true")
base.WriteRaw("1");
else
funcWriter(text);
break;
case 'f':
// Replace "false" with "0" (my apologies to 4- and 5-char long strings
// that actually begin with 'f').
//
if (text == "false")
base.WriteRaw( "0");
else
funcWriter(text);
break;
default:
funcWriter(text);
break;
}
}
else funcWriter(text);
}
// Needed when element text nodes are written.
public override void WriteRaw(string text)
{
this.Write(text, this._writeRaw);
}
// Needed when attribute text values are written.
public override void WriteString(string text)
{
this.Write(text, this._writeString);
}
}
- - -
If you create an XmlSerializer for the following trivial class, with both a boolean
attribute and element text node,
- - - ClassWithBools.cs
public class ClassWithBools
{
private bool _active, _passive;
public ClassWithBools( ) { ; }
public bool Active { get { return _active; } set { _active = value; } }
[System.Xml.Serialization.XmlAttribute]
public bool Passive { get { return _passive; } set { _passive = value; } }
}
- - -
and then serialize a simple instance of ClassWithBools, objectWithBools, into any
TextWriter wrapped in the BoolXmlTextWriter,
serializer.Serialize(
new BoolXmlTextWriter(
new StreamWriter(
File.OpenWrite( "../../dancesWithBools.xml")
)
)
);
the result you receive should look like the following (indented formatting added for
better readability),
- - - dancesWithBools.xml
<?xml version="1.0" encoding="utf-8"?>
<ClassWithBools
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="
http://www.w3.org/2001/XMLSchema" Passive="1">
<Active>0</Active>
</ClassWithBools>>
- - -
Of course, is a trivial matter to add additional overloads to the constructor so that it
can wrap other sinks besides TextWriter allowing you to use whatever you need to
serialize into for your application.
Derek Harmon