问题描述
在我们的项目中,我们extensivly使用XmlSerializer的。一次偶然的机会,我发现一个类W / OA参数的构造器。我认为这必须打破序列化进程,但事实并非如此。
通过研究这个问题,我发现,这XmlSerializer的序列化/反序列化的行为时,一个奇怪的的IEnumerable 的:
- 可枚举的所有元素序列
- 类是实施的添加(对象)要求的方法
- 在它忽略了,可能是在这个类中的所有其他属性。
- 在它调用与这个属性的getter和重用序列化的返回的实例(允许XmlSerializer的工作瓦特/ OA参数的构造函数)。
请看看下面的例子。野趣部分是ODD1,ODD2。需要注意的是good5和good6都是假的,我希望他们是真的。
还有一个原因是对这种行为?
我可以手动执行时的IXmlSerializable XmlSerializer的重用反序列化的属性返回一个实例?
System.Collections中使用;
使用System.Collections.Generic;
使用System.IO;
使用的System.Xml;
使用System.Xml.Schema;
使用的System.Xml.Serialization;
命名空间测试
{
公共静态类节目
{
公共静态无效的主要()
{
HostingClass主机=新HostingClass();
host.AutomaticSerialization.StringProperty =自动;
host.SelfImplementedSerialization.StringProperty =自我;
布尔good1 = host.AutomaticSerialization.FromConstructor ==参数;
布尔good2 = host.SelfImplementedSerialization.FromConstructor ==参数;
布尔good3 = host.AutomaticSerialization.StringProperty ==AUTO;
布尔good4 = host.SelfImplementedSerialization.StringProperty ==自我;
XmlSerializer的序列化=新的XmlSerializer(typeof运算(HostingClass));
使用(StringWriter的SW =新的StringWriter())
{
serializer.Serialize(SW,主机);
用(StringReader SR =新StringReader(sw.ToString()))
{
主机=(HostingClass)serializer.Deserialize(SR);
}
}
布尔good5 = host.AutomaticSerialization.FromConstructor == NULL; //为假
布尔good6 = host.AutomaticSerialization.StringProperty ==AUTO; //为假
布尔good7 = host.SelfImplementedSerialization.FromConstructor == NULL;
布尔good8 = host.SelfImplementedSerialization.StringProperty ==自我;
}
}
公共类HostingClass
{
私人SelfImplementedSerialization _selfImplementedSerialization;
公共SelfImplementedSerialization SelfImplementedSerialization
{
得到
{
返回_selfImplementedSerialization
? (_selfImplementedSerialization =新SelfImplementedSerialization(参数));
}
集合{_selfImplementedSerialization =价值; }
}
私人AutomaticSerialization _automaticSerialization;
公共AutomaticSerialization AutomaticSerialization
{
得到
{
返回_automaticSerialization
? (_automaticSerialization =新AutomaticSerialization(参数)); //反序列化返回的对象用于
}
集合{_automaticSerialization =价值; }
}
}
公共类SelfImplementedSerialization:IXmlSerializable的,IEnumerable的< INT>
{
公共SelfImplementedSerialization(){}
公共SelfImplementedSerialization(字符串参数)
{
FromConstructor =参数;
}
公共字符串StringProperty {获得;组; }
[XmlIgnore]
公共字符串FromConstructor {获得;组; }
公共无效的ReadXml(XmlReader的读者)
{
reader.ReadStartElement();
StringProperty = reader.ReadElementString(StringProperty);
reader.ReadEndElement();
}
公共无效中WriteXML(XmlWriter的作家)
{
writer.WriteElementString(StringProperty,StringProperty);
}
公众的IEnumerator< INT>的GetEnumerator()
{
收益率的回报1;
收益率回归2;
}
IEnumerator的IEnumerable.GetEnumerator(){返回的GetEnumerator(); }
公众的XmlSchema的getSchema(){返回NULL; }
}
公共类AutomaticSerialization:IEnumerable的<诠释>
{
// ODD1:序列化可能的W / O型的公共参数构造函数
//公共AutomaticSerialization(){}
公共AutomaticSerialization(字符串参数)
{
FromConstructor =参数;
}
// ODD2:元素没有序列号,只有IEnumerable接口是序列化
[的XmlElement(SP)]
公共字符串StringProperty {获得;组; }
[XmlIgnore]
公共字符串FromConstructor {获得;组; }
公众的IEnumerator< INT>的GetEnumerator()
{
收益率的回报1;
收益率回归2;
}
公共无效添加(对象o)
{
XmlSerializer的序列化的时候IEnumerables //要求
}
IEnumerator的IEnumerable.GetEnumerator(){返回的GetEnumerator(); }
}
}
的原因行为,这是它一贯的工作方式。
In our project we extensivly use the XmlSerializer. By chance I found a class w/o a parameterless contructor. I thought this must break the serialization process but it did not.
By investigating this issue I found out, that the XmlSerializer behaves strange when serializing/deserializing an IEnumerable:
- All elements of the enumerable are serialized
- The class is required to implement an Add(object) method
- It ignores all other properties that may be in this class.
- It calls a getter with this property and reuses the returned instance for serialization (which allows the XmlSerializer to work w/o a parameterless constructor).
Please have a look at the example that follows. Intersting parts are ODD1, ODD2. Note that good5 and good6 are false, when I expected them to be true.
Is there a reason for this behaviour?
Can I make XmlSerializer reuse an instance returned by a property for deserialization when implementing IXmlSerializable by hand?
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Test
{
public static class Program
{
public static void Main()
{
HostingClass host = new HostingClass();
host.AutomaticSerialization.StringProperty = "AUTO";
host.SelfImplementedSerialization.StringProperty = "SELF";
bool good1 = host.AutomaticSerialization.FromConstructor == "PARAMETER";
bool good2 = host.SelfImplementedSerialization.FromConstructor == "PARAMETER";
bool good3 = host.AutomaticSerialization.StringProperty == "AUTO";
bool good4 = host.SelfImplementedSerialization.StringProperty == "SELF";
XmlSerializer serializer = new XmlSerializer(typeof(HostingClass));
using (StringWriter sw = new StringWriter())
{
serializer.Serialize(sw, host);
using (StringReader sr = new StringReader(sw.ToString()))
{
host = (HostingClass)serializer.Deserialize(sr);
}
}
bool good5 = host.AutomaticSerialization.FromConstructor == null; //is false
bool good6 = host.AutomaticSerialization.StringProperty == "AUTO"; //is false
bool good7 = host.SelfImplementedSerialization.FromConstructor == null;
bool good8 = host.SelfImplementedSerialization.StringProperty == "SELF";
}
}
public class HostingClass
{
private SelfImplementedSerialization _selfImplementedSerialization;
public SelfImplementedSerialization SelfImplementedSerialization
{
get
{
return _selfImplementedSerialization
?? (_selfImplementedSerialization = new SelfImplementedSerialization("PARAMETER"));
}
set { _selfImplementedSerialization = value; }
}
private AutomaticSerialization _automaticSerialization;
public AutomaticSerialization AutomaticSerialization
{
get
{
return _automaticSerialization
?? (_automaticSerialization = new AutomaticSerialization("PARAMETER")); //the returned object is used while deserializing
}
set { _automaticSerialization = value; }
}
}
public class SelfImplementedSerialization : IXmlSerializable, IEnumerable<int>
{
public SelfImplementedSerialization() { }
public SelfImplementedSerialization(string parameter)
{
FromConstructor = parameter;
}
public string StringProperty { get; set; }
[XmlIgnore]
public string FromConstructor { get; set; }
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement();
StringProperty = reader.ReadElementString("StringProperty");
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("StringProperty", StringProperty);
}
public IEnumerator<int> GetEnumerator()
{
yield return 1;
yield return 2;
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public XmlSchema GetSchema() { return null; }
}
public class AutomaticSerialization : IEnumerable<int>
{
//ODD1: Serialization possible w/o public parameterless constructor
//public AutomaticSerialization() {}
public AutomaticSerialization(string parameter)
{
FromConstructor = parameter;
}
//ODD2: Element not serialized, only the IEnumerable Interface is serialized
[XmlElement("SP")]
public string StringProperty { get; set; }
[XmlIgnore]
public string FromConstructor { get; set; }
public IEnumerator<int> GetEnumerator()
{
yield return 1;
yield return 2;
}
public void Add(object o)
{
//requirement of XmlSerializer when serializing IEnumerables
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}
The reason for the behavior is that this is the way it has always worked.
From XmlSerializer class:
这篇关于XmlSerializer的和IEnumerable:序列化可能的W / O参数的构造函数:错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!