Как вы сериализуете / десериализуете список объектов с общим корневым классом? - PullRequest
1 голос
/ 30 июня 2009

Похожие: Как использовать полиморфизм в сериализации XML?

У меня есть класс, который я написал для сериализации пользовательских предпочтений на диске между сеансами приложения. Для чтения / записи я использую XmlSerializer.Deserialize () и XmlSerializer.Serialize (). Одно из свойств, которое сериализуется, представляет собой список подустановок для различных компонентов приложения. Для этого у меня есть что-то вроде следующего (свойство используется только во время сериализации):

private readonly Dictionary<SettingType, SubSettings> subSettings;    

[XmlArray("SubSettings")]
[XmlArrayItem("SubSetting", Type=typeof(DictionaryEntry))]
public DictionaryEntry[] _SubSettings
{
    get
    {
        int i = 0;

        //Make an array of DictionaryEntries to return 
        DictionaryEntry[] result = new DictionaryEntry[subSettings.Count];

        foreach( KeyValuePair<SettingType, SubSettings> setting in subSettings ) {
            DictionaryEntry entry = new DictionaryEntry( setting.Key, setting.Value );
            result[i] = entry;
            i++;
        }

        return result;
    }
    set
    {
        subSettings.Clear();
        for( int i = 0; i < value.Length; i++ )
            subSettings.Add( (SettingType)value[i].Key, (SubSettings)value[i].Value );
    }
}

Это отлично мне подходит, все значения словаря являются динамическими подустановками. Проблема в том, что теперь я хотел бы, чтобы некоторые объекты SubSettings были другого динамического типа (CoolSubSettings: SubSettings). Очевидная проблема заключается в том, что если я сделаю это, я не смогу общаться, так как XML читается, каким динамическим типом должен быть каждый узел SubSettings, и его дополнительные свойства не будут читаться или записываться.

1 Ответ

2 голосов
/ 30 июня 2009

Это потому, что сериализатор не знает всех типов, вы должны сказать ему, какие типы он должен использовать. Например, вы не можете попробовать следующий подход:

struct DictEntry<T>
{
   public SettingType Key;
   public T Value;
}

// ...

[XmlArray("SubSettings")]
[XmlArrayItem("SubSetting", Type=typeof(DictEntry<SubSettings>))]
[XmlArrayItem("CoolSubSetting", Type=typeof(DictEntry<CoolSubSettings>))]
public object[] _SubSettings
{
    // ...

Обновление: Еще одно решение вашей проблемы:

struct DictEntry
{
    public SettingType Key;        
    [XmlElement("SubSettingValue", Type=typeof(SubSettings))]        
    [XmlElement("CoolSubSettingValue", Type=typeof(CoolSubSettings))]
    public object Value;
}

[XmlArray("SubSettings")]
public DictEntry[] _SubSettings
{
    // ...

Я думаю, вы понимаете основную идею реализации? Кстати, я не уверен в наследовании в этом случае, и я не могу проверить это прямо сейчас. Но в случае проблем вы можете создать базового предка для SubSettings и CoolSubSettings.

...