XML 직렬화 가능 클래스에 매개 변수가없는 생성자가 필요한 이유 return

Xml 직렬화를 수행하는 코드를 작성 중입니다. 아래 기능으로.

public static string SerializeToXml(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

인수가 매개 변수가없는 생성자가없는 클래스의 인스턴스 인 경우 예외가 발생합니다.

처리되지 않은 예외 : System.InvalidOperationException : CSharpConsole.Foo에는 매개 변수가없는 생성자가 없으므로 직렬화 할 수 없습니다. System.Xml.Serialization.ModelScope.GetTypeModel (System.Xml.Serialization.ModelScope.GetTypeModel (System.Xml.Serialization.TypeScope.GetTypeDesc (Type type, MemberInfo sour e, Boolean directReference, Boolean throwOnError))에서 System.Xml.Serialization.ModelScope.GetTypeModel (Type type, System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (Type type, XmlRootAttribute root, String defaultNamespace)의 System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (부울 직접 참조)에서 System.Xml.Serialization의 System.Xml.Serialization.XmlSerializer..ctor (Type type, String defaultName space)입니다. XmlSerializer..ctor (유형)

XML 직렬화가 성공하려면 왜 매개 변수가없는 생성자가 있어야합니까?

편집 : cfeduke의 답변에 감사드립니다. 매개 변수가없는 생성자는 개인용 또는 내부 용일 수 있습니다.



답변

객체의 역 직렬화 과정에서 객체의 역 직렬화를 담당하는 클래스는 직렬화 된 클래스의 인스턴스를 만든 다음 인스턴스를 채운 후에 만 ​​직렬화 된 필드와 속성을 채 웁니다.

매개 변수가없는 한 생성자를 만들 private거나 internal원하는 경우 만들 수 있습니다 .


답변

의 제한 사항입니다 XmlSerializer. 주의 BinaryFormatterDataContractSerializer 하지 않는 그들이 에테르에서 초기화되지 않은 개체를 만들고 직렬화 복원시를 초기화 할 수 있습니다 -이 필요합니다.

xml을 사용 DataContractSerializer하고 있으므로 클래스를 사용 하고 [DataContract]/ [DataMember]로 표시하는 것을 고려할 수 있지만이 경우 스키마가 변경됩니다 (예를 들어, [XmlAttribute]모든 것이 요소가 됨).

업데이트 : 정말로 알고 싶다면 생성자를 호출하지 않고 객체를 만드는 데 BinaryFormatter사용 FormatterServices.GetUninitializedObject()합니다. 아마 위험하다; 너무 자주 사용하지 않는 것이 좋습니다 ;-p MSDN에 대한 설명도 참조하십시오.

객체의 새 인스턴스가 0으로 초기화되고 생성자가 실행되지 않기 때문에 객체는 해당 객체에 의해 유효한 것으로 간주되는 상태를 나타내지 않을 수 있습니다. 현재 방법은 사용자가 모든 필드를 즉시 채우려는 경우 역 직렬화에만 사용해야합니다. 변경 불가능한 유형의 빈 인스턴스를 작성하는 것은 아무 목적이 없기 때문에 초기화되지 않은 문자열을 작성하지 않습니다.

자신의 직렬화 엔진을 가지고 있지만 그것을 사용하려고하지 않습니다 FormatterServices. 생성자 ( 모든 생성자)가 실제로 실행 되었음을 알고 싶습니다 .


답변

정답은 : 이유가 없습니다.

이름과 달리 XmlSerializer클래스는 직렬화뿐만 아니라 역 직렬화에도 사용됩니다. 클래스에서 특정 검사를 수행하여 작동하는지 확인하고 일부 검사는 직렬화 해제와 관련이 있지만 나중에 수행하려는 작업을 모르기 때문에 어쨌든 수행합니다.

클래스가 통과하지 못한 확인은 역 직렬화와 관련된 확인 중 하나입니다. 다음과 같은 일이 발생합니다.

  • 역 직렬화 중에 XmlSerializer클래스는 사용자 유형의 인스턴스를 작성해야합니다.

  • 형식의 인스턴스를 만들려면 해당 형식의 생성자를 호출해야합니다.

  • 생성자를 선언하지 않은 경우 컴파일러는 이미 기본 매개 변수없는 생성자를 제공했지만 생성자를 선언 한 경우 사용 가능한 유일한 생성자입니다.

  • 따라서 선언 한 생성자가 매개 변수를 허용하는 경우 클래스를 인스턴스화하는 유일한 방법은 매개 변수를 허용하는 해당 생성자를 호출하는 것입니다.

  • 그러나 XmlSerializer매개 변수가없는 생성자를 제외한 생성자를 호출 할 수는 없습니다. 매개 변수를 허용하는 생성자에 전달할 매개 변수를 모르기 때문입니다. 따라서 클래스에 매개 변수가없는 생성자가 있는지 확인하고 그렇지 않은 경우 실패합니다.

따라서 XmlSerializer클래스가 직렬화와 관련된 검사 만 수행하는 방식으로 작성된 경우 매개 변수가없는 생성자를 가질 필요가있는 직렬화에 대해서는 전혀 없기 때문에 클래스가 전달됩니다.

다른 사람들이 이미 지적했듯이 문제의 빠른 해결책은 단순히 매개 변수가없는 생성자를 추가하는 것입니다. 불행히도 readonly생성자 매개 변수에서 멤버를 초기화 할 수 없기 때문에 더러운 솔루션 입니다.

이 모든 것 외에도 XmlSerializer클래스 매개 변수가없는 생성자가없는 클래스의 직렬화를 해제 할 수있는 방식으로 작성되었을 있습니다. 이 걸릴 것 모두가 사용하게 될 것 “팩토리 메소드 디자인 패턴”(위키 백과) . 외관상으로, Microsoft는 이러한 디자인 패턴이 DotNet 프로그래머에게는 너무 진보되어 있기 때문에 불필요하게 그러한 것들과 혼동해서는 안됩니다. 따라서 Microsoft에 따르면 DotNet 프로그래머는 매개 변수가없는 생성자를 고수해야합니다.


답변

우선, 이것은 documentation에 쓰여진 것입니다 . 나는 그것이 주요한 분야가 아니라 당신의 계급 분야 중 하나라고 생각합니다-그리고 deserialiser가 어떻게 매개 변수없는 구성없이 그것을 다시 구성하기를 원하십니까?

생성자를 비공개로 만드는 해결 방법이 있다고 생각합니다.