根据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
,但也没有。
有什么想法吗?
答案 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
祝你好运!