【发布时间】:2018-06-09 17:24:18
【问题描述】:
我正在尝试在名为GenericSerializable 的自定义属性后面实现 C# 中基本序列化的抽象。本质上,我希望此属性在应用于公共属性时向某些序列化程序(无论是 XML、JSON、Protobuf 等)指示该属性应该被序列化,如果它不存在则不应该被序列化。目前,我可以获得特定属性是否具有该属性的信息,但我正在努力实现 XML 序列化程序。这是我的测试继承结构:
public abstract class SerializableObjectBase
{
protected int _typeIndicator;
[GenericSerializable]
public int TypeIndicator
{
get
{
return _typeIndicator;
}
}
public SerializableObjectBase()
{
_typeIndicator = 0;
}
}
public class SerializableObjectChildOne : SerializableObjectBase
{
private int _test;
public int Test
{
get
{
return _test;
}
set
{
_test = value;
}
}
public SerializableObjectChildOne() : base()
{
_test = 1234;
_typeIndicator = 1;
}
}
public class SerializableObjectChildTwo : SerializableObjectChildOne
{
private List<int> _list;
public List<int> List
{
get
{
return _list;
}
}
public SerializableObjectChildTwo() : base()
{
_list = new List<int>();
_typeIndicator = 2;
}
}
我希望此示例的 XML 看起来像:
<?xml version="1.0" encoding="utf-8"?>
<SerializableObjectChildTwo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TypeIndicator>2</TypeIndicator>
</SerializableObjectChildTwo>
但它看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<SerializableObjectChildTwo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Test>1234</Test>
</SerializableObjectChildTwo>
序列化代码如下:
using (FileStream fs = new FileStream(".\\output.xml", FileMode.Create))
{
// object to serialize
SerializableObjectChildTwo s = new SerializableObjectChildTwo();
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
// check whether each property has the custom attribute
foreach (PropertyInfo property in typeof(SerializableObjectChildTwo).GetProperties())
{
XmlAttributes attrbs = new XmlAttributes();
// if it has the attribute, tell the overrides to serialize this property
if (property.CustomAttributes.Any((attr) => attr.AttributeType.Equals(typeof(GenericSerializable))))
{
Console.WriteLine("Adding " + property.Name + "");
attrbs.XmlElements.Add(new XmlElementAttribute(property.Name));
}
else
{
// otherwise, ignore the property
Console.WriteLine("Ignoring " + property.Name + "");
attrbs.XmlIgnore = true;
}
// add this property to the list of overrides
overrides.Add(typeof(SerializableObjectChildTwo), property.Name, attrbs);
}
// create the serializer
XmlSerializer xml = new XmlSerializer(typeof(SerializableObjectChildTwo), overrides);
// serialize it
using (TextWriter tw = new StreamWriter(fs))
{
xml.Serialize(tw, s);
}
}
有趣的是,如果我将GenericSerializable 属性添加到SerializableObjectChildTwo 中的List 属性,它会按预期运行。问题是,由于某种原因,尽管我添加了 attrbs.XmlIgnore = true,Test 仍在序列化,尽管我将其明确添加到 XmlAttributeOverrides,TypeIndicator 仍未序列化。
我是否错误地使用了覆盖?我不需要任何花哨的 XML 模式或任何东西,我只想根据我的自定义属性的存在与否来序列化/不序列化公共属性。
提前致谢。
【问题讨论】:
-
属性
TypeIndicator不会被序列化,因为它没有setter 和getter,如Why are properties without a setter not serialized 中所述。但是List是序列化的,因为它是一个预分配的集合,并且对于仅获取集合属性不存在此限制,如this answer 至Implementing IXmlSerializable Requires Collection Property to Have Setter 中所述。 -
顺便说一下,您需要缓存并重复使用序列化程序,如Memory Leak using StreamReader and XmlSerializer 中所述。
-
我实际上意识到缓存的必要性,我只是没有在这个例子中包含它。二传手是必要的,所以谢谢你抓住它。但是,
XmlAttributeOverrides的问题仍然存在:即使我设置了attrbs.XmlIgnore = true,该属性仍然是序列化的。
标签: c# .net xml serialization xmlserializer