우리 프로젝트에서는 XmlSerializer를 광범위하게 사용합니다. 우연히 매개 변수없는 생성자가없는 클래스를 찾았습니다. 직렬화 프로세스를 중단해야한다고 생각했지만 그렇지 않았습니다. 이 문제를 조사하여XmlSerializer 및 IEnumerable : 매개 변수없는 생성자없이 직렬화 가능 : 버그?
내가 XmlSerializer를이IEnumerable을 역 직렬화/직렬화 할 때 이상한 동작하는지, 발견 다음 열거의
- 모든 요소를 직렬화
- 클래스는 구현하기 위해 필요 추가 (개체) 메서드
- 이 클래스에있을 수있는 다른 모든 속성을 무시합니다.
- 이 속성을 사용하여 getter를 호출하고 반환 된 인스턴스를 serialization에 다시 사용합니다 (XmlSerializer가 매개 변수없는 생성자없이 작동 할 수 있음).
다음 예를 살펴보십시오. 삽입 부분은 ODD1, ODD2입니다. good5와 good6은 내가 사실 일 것으로 예상했을 때 거짓입니다.
이 동작에 대한 이유가 있습니까?
IXmlSerializable을 손으로 구현할 때 XmlSerializer가 deserialization을 위해 속성에서 반환 한 인스턴스를 다시 사용하도록 할 수 있습니까?
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(); }
}
}
안녕하세요 John, 답변 해 주셔서 감사합니다.어떤 경우에는 getter가 먼저 호출되고 반환 된 객체는 deserialization에 사용되며, 다른 경우에는 setter가 먼저 scatch에서 deserialize 된 객체와 함께 호출됩니다. 그건 나에게별로 의미가 없다. – mklein
@mklein : sense와 XML Serializer는 실제로 섞이지 않습니다. 이 "소시지"가 어떻게 만들어 졌는지 알기를 원한다면 소스 코드를 살펴 보는 것이 좋습니다. –
Re : "동작의 이유는 이것이 항상 효과가 있었던 것입니다." 같은 소리 : - 왜 당신은 항상 사과를 먹고 있습니까? - 내가 사과를 먹는 이유는 내가 항상 그들을 먹고 있었기 때문이다. – Vova