2013-09-03 1 views
2

두 클래스가 있고 하나는 다른 클래스를 상속받으며 XmlSerializer를 사용하여 자식을 serialize/deserialize해야한다고 가정합니다. 그러나 부모에게는 직렬화 할 수없는 멤버가 포함되어 있습니다 (예 : 사전).XmlSerializer - 상속되는 직렬화 할 수없는 멤버 무시

public class Parent { 

    public Dictionary<string, int> dictionary; 
} 

상위 클래스는 다른 많은 스크립트에 사용되는 라이브러리입니다. 수정할 수 없습니다. 이제 자식 클래스는 직렬화 멤버들을 포함

public class Child : Parent { 

    [XmlElement] 
    public int foo; 

} 

시리얼 라이저를 호출하려고, 나는 사전이 직렬화 가능하지 않다는 오류가 발생합니다. JSON에서 직렬화하려고 할 때, 나는 경고 가격으로 도망 갈 수 있었다. 난 그냥 같은 이름과 유형을 가진 다른 회원을 생성하고, ScriptIgnore을 사용 :

public class Child : Parent { 

    public int foo; 

    [ScriptIgnore] 
    public Dictionary<string, int> dictionary; 

} 

내가 다시 여기에 (XmlIgnore를 사용하여) 같은 트릭을 시도하지만 잘에 작동하지 않았다, 오류가 동일 . 필자가이 문제를 해결할 수있는 유일한 방법은 xml de/serialize를 제공하고 값을 적절한 위치에 다시 복사하는 별도의 클래스를 만드는 것입니다.

누구든지이 문제를 해결하는 더 좋은 방법을 알고 있습니까? XmlSerializer가 어떤 식 으로든 부모 사전을 잊어 버릴 수 있습니까?

답변

4

내가 말할 항상 말을하고 할 매우 먼저 : 기존 모델을 직렬화하는 것은 까다로운 얻는 경우에 - 다음, 심지어 원격으로 어색 정지 것을하고. 별도의 DTO 모델, 즉 일련 번호 (실제로는 특정 직렬 프로그램에 맞게 조정 된 것) 전용으로 으로 만든 모델을 만드는 데 2 ​​분이 소요됩니다. 이제 올바른 올바른 유형, 올바른 구성원, 올바른 특성 및 올바른 레이아웃을 배치합니다. 정적 변환 연산자는 여기에서 훌륭하게 작동합니다. 그래서 내가 말하고자하는 것은 : ParentDtoChildDto (귀하의 이름은 다를 수 있음)을 만드십시오; 3 분이 걸릴 것이고, 효과가있을 것입니다. 이제

, 다시 질문 ...

XmlSerializer 입력의 선언 클래스에서 보이는; 속성과 조건부 직렬화 모두에 대해, 아니오 :이 시점에서 유형 모델에 추가 할 수 없습니다. 그러나 또 다른 옵션이 있습니다. XmlAttributeOverrides을 사용하여 사전 구성원에 [XmlIgnore]이 있다고 가장 할 수 있습니다.그러나, 몇 가지 중요한주의 사항 :

  • XmlAttributeOverrides API는 faff의 비트가
  • 그것입니다 (예는 MSDN을 참조)를 사용하는 것입니다 중요한 만이 일단을 그와 그런 다음이 방법으로 만든 XmlSerializer을 저장하고 다시 사용하십시오. 기본적으로 만약 이 아니라면, new 시리얼 라이저와 어셈블리 이 결코 언로드되어가 아닌 새로운 동적 어셈블리를 생성 할 것이므로 메모리를 낭비 할 것입니다. 간단히 용도 (new XmlSerializer(someType) 등)에는 이에 대한 inbuilt 캐시가 있습니다.

    using System; 
    using System.Collections.Generic; 
    using System.Xml.Serialization; 
    public class Parent { 
        public Dictionary<string, int> WantToIgnoreThis { get; set; } 
    }  
    public class Child : Parent { 
        public int Foo { get; set; } 
    } 
    static class Program 
    { 
        static readonly XmlSerializer customSerializer; 
    
        static Program() 
        { 
         var xao = new XmlAttributeOverrides(); 
         xao.Add(typeof(Parent), "WantToIgnoreThis", new XmlAttributes { 
          XmlIgnore = true 
         }); 
         customSerializer = new XmlSerializer(typeof(Child), xao); 
        } 
        static void Main() 
        { 
         //var ser = new XmlSerializer(typeof(Child)); 
         // ^^ this would fail 
    
         customSerializer.Serialize(Console.Out, new Child { 
          Foo = 123 
         }); 
        } 
    } 
    
    :하지만 XmlAttributeOverrides 사용 다시

하지 않지만, XmlAttributeOverrides 모든이의 간섭이는 XmlAttributeOverrides을 사용하는 기본 DTO

예를 만드는 것보다 더 많은 작품입니다

특별히 static 필드가 serializer를 캐시하는 데 사용되는 방법에 유의하십시오.

1

IXmlSerializable을 직접 구현하고 ReadXml(XmlReader reader)WriteXml(XmlWriter writer)의 세부 사항을 처리 할 수 ​​있습니다. XmlSerializer은 클래스가 자체 serializer를 생성하는 대신 클래스를 구현하는 경우 해당 메소드를 호출합니다.

public class Child : Parent, IXmlSerializable 
{ 
    public int Foo { get; set; } 
    public Dictionary<string, int> Dictionary { get; set; } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement("Foo"); 
     writer.WriteValue(this.Foo); 
     writer.WriteEndElement(); 
    } 

    void ReadXml(XmlReader reader) 
    {    
     var wasEmpty = reader.IsEmptyElement; 
     reader.Read(); 

     if (wasEmpty) 
     { 
      return; 
     } 

     reader.ReadStartElement("Foo"); 
     this.Foo = reader.ReadContentAsInt(); 
     reader.ReadEndElement(); 
    } 
} 
+0

'IXmlSerializable' API (특히 읽기)는 사소한 경우를 제외하고는 아무 것도 얻을 수없는 것으로 유명합니다. 복잡한 일이라면 엄청난 코드 작업이되거나 DOM API ('XmlDocument','XDocument')의 오버 헤드가 발생하여 복잡한 읽기 메소드를 직접 작성하는 고통을 피할 수 있습니다. 내 돈을 위해 직렬화를 살펴 보는 데 상당한 시간을 소비하는 사람으로 이렇게 말합니다. 'IXmlSerializable'을 구현하는 것만으로도 큰 문제가되지 않습니다. 물론 YMMV. –

관련 문제