2014-05-21 1 views
0

I는 다음과 같습니다 게임 데이터 클래스가 있습니다재산권의 파생 클래스가 삭제됩니다 (즉, 기본 클래스로 대체) XML 직렬화 복원에

public class SaveGameData { 

    public virtual List<PropertyContainer> properties {get; set; } 

} 

그리고 너무 이러한 클래스 :

public class PropertyContainer { 

    public Property property {get; set; }//Could be set to DerivedProperty 

} 
public class Property { 
    public int BasePropertyData {get; set;} 
} 
public class DerivedProperty : Property { 
    public int DerivedPropertyData {get; set; }  
} 

을 그리고 저장/재생 세션간에이 데이터를로드 할 노력하고있어, XML serialization/deserialization이이 프로세스를 사용하고 있습니다.

PropertyContainer container = new PropertyContainer(); 
container.property = derivedProperty; 

컨테이너가 직렬화

, 파생 클래스와 그 특수 :

문제는 PROPERTYCONTAINER 클래스에서 파생 된 속성이 때로는 속성 클래스에 subistution이 같은 것을 사용한다는 것입니다 속성도 저장되며 문제는 없습니다.

직렬화 프로세스가 파생 클래스를 인식하고 올바르게 XML 파일에 저장되는대로 작동하는 것 같군
serializer = new System.Xml.Serialization.XmlSerializer(typeof(SaveGameData)); 

SaveGameData dataToSave = GetSaveGameData(); 
using (var stream = new StringWriter()) { 
serializer.Serialize(stream, dataToSave); 
...write to file... 

} 

, XML 출력은 다음과 같습니다 :

<?xml version="1.0" encoding="utf-16"?> 
<SaveGameData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

    <properties> 

    <PropertyContainer> 

     <property xsi:type="DerivedProperty"> 

     <BasePropertyData>1</BasePropertyData> 
     <DerivedPropertyData>1</DerivedPropertyData> 

     </property> 

    </PropertyContainer> 

    </properties> 

</SaveGameData> 
을 여기

는 직렬화 코드입니다

그러나 XML 파일을 deserialize 할 때 모든 파생 클래스가 삭제됩니다. 기본 클래스를 생성 할 것이다. (속성 가정 할 DerivedProperty이며, 예컨대 saveGameData.properties[0].GetType()) 유래 속성 GetType()를 호출

SaveGameData result; 
string data = ReadSaveGameData(); 
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SaveGameData)); 

     using (StringReader stream = new StringReader(savedGame)) { 
      result = (SaveGameData)serializer.Deserialize(stream); 

     } 

XML 데이터를로드 한 후 수단, 즉 Property; 여기서 역 직렬화 코드의 확장에 의해, 모든 DerivedProperty의 프롭퍼티는 파기됩니다. 문제가 있습니다.

P.S

: 나는 XmlInclude 속성을 추가했지만, 아무것도 변경되지 :

[System.Xml.Serialization.XmlInclude(typeof(DerivedProperty))] 
public class Property { 

... 

} 

가 어떻게이 문제를 해결합니까? 내 접근 방식에 대한 실행 가능한 대안이 있습니까?

답변

0

[XmlInclude(typeof(DerivedProperty))]Property 클래스는 일을해야 장식합니다. 실제로, 그것없이, XmlSerializer은 심지어 당신이 DerivedProperty을 처음부터 직렬화하게하지 않을 것입니다!

다음 프로그램은 코드를 기반으로 한 작동 예제입니다. 시스템 콘솔의 콘솔 출력이 True인지 확인하십시오. 그렇다면 코드가 원래 시도와 다른 점을 판별해야합니다. 그런 다음 질문을 업데이트하여 더 깊이 파고들 수 있습니다.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Xml.Serialization; 

class Program 
{ 
    static void Main() 
    { 
     string savedGame = @" 
<SaveGameData xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
    <properties> 
    <PropertyContainer> 
     <property xsi:type='DerivedProperty'> 
     <BasePropertyData>1</BasePropertyData> 
     <DerivedPropertyData>1</DerivedPropertyData> 
     </property> 
    </PropertyContainer> 
    </properties> 
</SaveGameData>"; 
     XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData)); 
     SaveGameData result; 

     using (StringReader stream = new StringReader(savedGame)) 
     { 
      result = (SaveGameData)serializer.Deserialize(stream); 
     } 

     Console.WriteLine(result.properties[0].property is DerivedProperty); // True 
    } 
} 

public class SaveGameData 
{ 
    public virtual List<PropertyContainer> properties { get; set; } 
} 

public class PropertyContainer 
{ 
    public Property property { get; set; }//Could be set to DerivedProperty 
} 

[XmlInclude(typeof(DerivedProperty))] 
public class Property 
{ 
    public int BasePropertyData { get; set; } 
} 

public class DerivedProperty : Property 
{ 
    public int DerivedPropertyData { get; set; } 
} 
+0

이 존재하지 않는 버그가 어떻게 나를 통과했는지는 모르겠지만 지옥은 내 시간을 낭비했다. 지적 해 주셔서 감사합니다. – Abdulaziz

0

하나의 옵션은 DataContractSerializer으로 전환하는 것입니다. 그런 다음 KnownTypeAttribute을 사용하여 하위 클래스를 식별하십시오.

public class PropertyContainer { 

    public Property property {get; set; }//Could be set to DerivedProperty 

} 
[KnownType(typeof(DerivedProperty))] 
public class Property { 
    public int BasePropertyData {get; set;} 
} 
public class DerivedProperty : Property { 
    public int DerivedPropertyData {get; set; }  
}