【问题标题】:serialize default attributes using XmlSerializer使用 XmlSerializer 序列化默认属性
【发布时间】:2018-11-02 19:05:42
【问题描述】:

基于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 中的当前位置找到。

所以我假设总是为defattr 选择true 可以解决问题,但它不会改变输出中的任何内容。我也试过false,也没用。

有什么想法吗?

【问题讨论】:

标签: c# xml-serialization xmlserializer


【解决方案1】:

在您的示例中,您混合了 ComponentModel 和 Serialization 注释,它们似乎没有按预期工作。我遍历了我能想到的所有排列设置,得到的结果出乎意料。

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

祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多