[C#] XmlSerializer-유형을 반영하는 중에 오류가 발생했습니다

C # .NET 2.0을 사용하면 [Serializable]속성 이있는 복합 데이터 클래스가 있습니다 . XMLSerializer클래스를 만들고 생성자에 전달합니다.

XmlSerializer serializer = new XmlSerializer(typeof(DataClass));

예외가 발생했습니다.

유형을 반영하는 중에 오류가 발생했습니다.

데이터 클래스 내부에는 또 다른 복합 객체가 있습니다. 이것도 [Serializable]속성 을 가져야합니까 , 아니면 최상위 객체에 포함 시켜서 내부의 모든 객체에 재귀 적으로 적용합니까?



답변

당신이 받고있는 내부 예외를보십시오. 직렬화에 문제가있는 필드 / 프로퍼티를 알려줍니다.

속성으로 장식하여 필드 / 속성을 XML 직렬화에서 제외 할 수 있습니다 [XmlIgnore].

XmlSerializer[Serializable]속성을 사용하지 않으므로 문제가 의심됩니다.


답변

직렬화 된 클래스에는 기본 (즉, 매개 변수가없는) 생성자가 있어야합니다. 생성자가 전혀 없다면 괜찮습니다. 그러나 매개 변수가있는 생성자가있는 경우 기본 구성 요소도 추가해야합니다.


답변

비슷한 문제가 있었는데 serializer가 동일한 이름을 가진 2 개의 클래스 (하나는 다른 클래스의 하위 클래스)를 구별 할 수 없다는 것이 밝혀졌습니다. 내부 예외는 다음과 같습니다.

‘Types BaseNamespace.Class1’및 ‘BaseNamespace.SubNamespace.Class1’은 모두 네임 스페이스 ”의 XML 유형 이름 ‘Class1’을 사용합니다. XML 속성을 사용하여 유형에 고유 한 XML 이름 및 / 또는 네임 스페이스를 지정하십시오.

여기서 BaseNamespace.SubNamespace.Class1은 BaseNamespace.Class1의 서브 클래스입니다.

내가해야 할 일은 클래스 중 하나에 속성을 추가하는 것이 었습니다 (기본 클래스에 추가했습니다).

[XmlType("BaseNamespace.Class1")]

참고 : 클래스 계층이 더 있으면 속성도 추가해야합니다.


답변

또한 XmlSerializer추상 속성을 직렬화 할 수 없다는 점에 유의 하십시오. 여기 내 질문을 참조 하십시오 (솔루션 코드를 추가했습니다).

XML 직렬화 및 상속 된 유형


답변

내가 가장 일반적인 이유 :

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members


답변

직렬화 그래프의 모든 개체는 직렬화 가능해야합니다.

이후 XMLSerializer블랙 박스 직렬화 프로세스로 추가로 디버깅하려면이 링크를 확인하십시오.

XmlSerializer가 임시 어셈블리를 출력하는 위치 변경

방법 : .NET XmlSerializer 생성 어셈블리로 디버그


답변

특정 속성 (예 : Dictionary 또는 클래스)을 처리해야하는 경우 IXmlSerialiable 인터페이스를 구현하면 보다 자세한 코딩 비용으로 더 많은 자유 얻을 수 있습니다 .

public class NetService : IXmlSerializable
{
    #region Data

        public string Identifier = String.Empty;

        public string Name = String.Empty;

        public IPAddress Address = IPAddress.None;
        public int Port = 7777;

    #endregion

    #region IXmlSerializable Implementation

        public XmlSchema GetSchema() { return (null); }

        public void ReadXml(XmlReader reader)
        {
            // Attributes
            Identifier = reader[XML_IDENTIFIER];
            if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
            if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
        }

        public void WriteXml(XmlWriter writer)
        {
            // Attributes
            writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
            writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
            writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
        }

        private const string XML_IDENTIFIER = "Id";

        private const string XML_NETWORK_ADDR = "Address";

        private const string XML_NETWORK_PORT = "Port";

    #endregion
}

XmlSerializer를 “확장”하는 정교한 방법을 구현하는 우아한 방법을 보여주는 흥미로운 기사 가 있습니다 .


기사는 말합니다 :

IXmlSerializable은 공식 문서에 포함되어 있지만 문서는 공용으로 사용되지 않으며 그 이상의 정보는 제공하지 않습니다. 이는 개발 팀이 확장 성 후크를 수정, 비활성화 또는 완전히 제거 할 수있는 권한을 보유하고 있음을 나타냅니다. 그러나 이러한 불확실성을 수용하고 향후 가능한 변경 사항을 처리 할 수있는 한,이를 활용할 수없는 이유는 없습니다.

이것이 IXmlSerializable너무 복잡한 구현을 피하기 위해 자신의 클래스 를 구현하는 것이 좋습니다 .

XmlSerializer리플렉션을 사용하여 사용자 정의 클래스 를 구현하는 것이 간단 할 수 있습니다 .