如何让XmlSerializer将bool编码为是/否?

Blo*_*ard 15 c# boolean xml-serialization

我正在将xml发送到另一个程序,它希望布尔标志为"是"或"否",而不是"真"或"假".

我有一个类定义如下:

[XmlRoot()]
public class Foo {
    public bool Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我序列化它时,我的输出如下所示:

<Foo><Bar>true</Bar></Foo>
Run Code Online (Sandbox Code Playgroud)

但我希望它是这样的:

<Foo><Bar>yes</Bar></Foo>
Run Code Online (Sandbox Code Playgroud)

我可以在序列化时这样做吗?我宁愿不必诉诸于此:

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

    [XmlElement("Bar")]
    public string BarXml { get { return (Bar) ? "yes" : "no"; } }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我还希望能够再次反序列化此数据.

Blo*_*ard 22

好的,我一直在研究这个问题.这是我想出的:

// 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将我的Foo类更改为:

[XmlRoot()]
public class Foo {      
    public YesNo Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,因为YesNo可以隐式转换为bool(反之亦然),您仍然可以执行此操作:

Foo foo = new Foo() { Bar = true; };
if ( foo.Bar ) {
   // ... etc
Run Code Online (Sandbox Code Playgroud)

换句话说,你可以像对待bool一样对待它.

而且!它序列化为:

<Foo><Bar>yes</Bar></Foo>
Run Code Online (Sandbox Code Playgroud)

它也正确地反序列化.

可能有一些方法可以让我的XmlSerializer自动将bool它遇到的任何s转换为YesNos - 但我还没有找到它.任何人?


Che*_*eso 8

非常简单.使用代理财产.在实际属性上应用XmlIgnore.代理是一个字符串,必须使用带有元素名称覆盖的XmlElement属性.指定覆盖中实际属性的名称.代理属性根据实际属性的值进行不同的序列化.您还必须为Surrogate提供一个setter,并且setter应该适当地设置实际属性,无论它序列化什么值.换句话说,它需要双向进行.

剪断:

    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!"); }
        }

    }
Run Code Online (Sandbox Code Playgroud)

单击此处获取完整的可编译源示例.

  • 是的,但这就是我在问题中给出的例子..我想知道是否有更好的*方式:) (2认同)