使用XmlSerializer序列化默认属性

时间:2018-05-23 17:35:11

标签: c# xml-serialization xmlserializer

根据this帖子,我尝试创建一个XmlTextWriter子类,它写入所有属性值,甚至是默认属性值。但我无法使其发挥作用。有人可以帮忙吗?

这是我要序列化的类:

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlType(AnonymousType = true)]
[System.Xml.Serialization.XmlRoot(Namespace = "", IsNullable = false)]
public class Foo
{
    public string content { get; set; }

    [System.Xml.Serialization.XmlAttribute()]
    [System.ComponentModel.DefaultValue(true)]
    public bool isActive { get; set; }
}

这是我创建Foo实例并将其序列化为字符串的代码:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces(
    new XmlQualifiedName[] { new XmlQualifiedName("", "") });
    // I need that for not writing a namespace during serialization
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
Foo f = new Foo();
f.content = "hello";
f.isActive = false;

string fStr;
using (MemoryStream ms = new MemoryStream())
using (XmlWriter wr = new XmlTextWriter(ms, new UTF8Encoding(false)))
{
    serializer.Serialize(wr, f, ns);
    ms.Position = 0;
    using (StreamReader sr = new StreamReader(ms))
    {
        fStr = sr.ReadToEnd();
    }
}

此代码将为我提供fStr的以下内容:

<?xml version="1.0" encoding="utf-8"?><Foo><content>hello</content></Foo>

但我想明确写出默认值,即

<?xml version="1.0" encoding="utf-8"?><Foo isActive="true"><content>hello</content></Foo>

所以我创建了一个XmlTextWriter的子类,并用new XmlTextWriter(...)替换了上面的new DefaultValueXmlTextWriter(...)。这是我的DefaultValueXmlTextWriter课程:

public class DefaultValueXmlTextWriter : XmlTextWriter
{

    public DefaultValueXmlTextWriter(Stream s, Encoding e) : base(s, e) { }
    public DefaultValueXmlTextWriter(string s, Encoding e) : base(s, e) { }
    public DefaultValueXmlTextWriter(TextWriter t) : base(t) { }

    public override void WriteAttributes(XmlReader reader, bool defattr)
    {
        base.WriteAttributes(reader, true);
    }
}

base.WriteAttributes的移民说:

  

在派生类中重写时,写出所有属性   在XmlReader中的当前位置找到。

所以我假设总是为true选择defattr会有效,但它不会改变输出中的任何内容。我也试过了false,但也没有。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

在您的示例中,您正在混合ComponentModel和序列化注释,但它们看起来并不像预期的那样工作。我查看了我能想到的每个排列设置,我得到的结果是出乎意料的。

var foo = new Foo();
foo.content = "hello";
//foo.isActive is left undefined
Console.WriteLine($"foo.isActive is left undefined");
Console.WriteLine($"foo.isActive = {foo.isActive}");
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
string file = "File.xml";
using (StreamWriter sw = new StreamWriter(file))
{
    serializer.Serialize(sw,foo);
}
bool attExists = File.ReadAllText(file).Contains("isActive");
Console.WriteLine($"It is {attExists} that isActive exists in {file}");
using (StreamReader sr = new StreamReader(file))
{
    Foo test = (Foo)serializer.Deserialize(sr); 
    Console.WriteLine(test.isActive);
}

代码的第3行被更改并反映在测试第一行的输出中的结果

foo.isActive is left undefined
foo.isActive = False
It is True that isActive exists in File.xml
False

foo.isActive = true;
foo.isActive = True
It is False that isActive exists in File.xml
False

foo.isActive = false;
foo.isActive = False
It is True that isActive exists in File.xml
False

如果您将结果补充到另一个班级,那么您的结果将不会那么好。似乎所有注释都是告诉序列化程序如果它是默认值则不输出值。

就个人而言,我会通过默认公共构造函数中的值并一起忽略注释来实现此目的。意图是更明确的,重新设计Xmlserializer是方式,方式矫枉过正,并可能带来其他意想不到的后果。

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlType(AnonymousType = true)]
[System.Xml.Serialization.XmlRoot(Namespace = "", IsNullable = false)]
public class Foo
{
    public string content { get; set; }
    [System.Xml.Serialization.XmlAttribute()]
    public bool isActive { get; set; }
    public Foo()
    {
        isActive = true;
    }
}

运行相同的测试会产生更可预测的结果。

foo.isActive is left undefined;
foo.isActive = True
It is True that isActive exists in File.xml
True

foo.isActive = true;
foo.isActive = True
It is True that isActive exists in File.xml
True

foo.isActive = false;
foo.isActive = False
It is True that isActive exists in File.xml
False
祝你好运!