DataContractSerializer DeSerialize Словарь перечисления (и двойного)

Я пытаюсь преобразовать XML в объект. Объект и xml выглядят следующим образом:

    <?xml version="1.0" encoding="utf-16"?>
<SystemData xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07">
<SystemBaseMVA>100</SystemBaseMVA>
<Voltage xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d2p1:KeyValueOfVariantdoubleM9TNTpwj>
        <d2p1:Key>Rated</d2p1:Key>
        <d2p1:Value>400</d2p1:Value>
    </d2p1:KeyValueOfVariantdoubleM9TNTpwj>
    <d2p1:KeyValueOfVariantdoubleM9TNTpwj>
        <d2p1:Key>Actual</d2p1:Key>
        <d2p1:Value>400</d2p1:Value>
    </d2p1:KeyValueOfVariantdoubleM9TNTpwj>
</Voltage>
</SystemData>

Объект...

[DataContract]
public class SystemData
{
    private readonly double _ratedVoltage;
    private readonly double _actualVoltage;

    #region ctor
    internal SystemData(
        double systemBaseMva,
        double ratedVoltage,
        double actualVoltage)
    {
        SystemBaseMVA = systemBaseMva;
        _ratedVoltage = ratedVoltage;
        _actualVoltage = actualVoltage;
    }
    #endregion

    #region Properties
    [DataMember]
    public double SystemBaseMVA { get; private set; }

    [DataMember]
    public Dictionary<Variant, double> Voltage
    {
        get
        {
            return new Dictionary<Variant, double>
            {
                {Variant.Rated, _ratedVoltage},
                {Variant.Actual, _actualVoltage}
            };
        }
    }
    #endregion

}

Перечисление:

[DataContract(Name = "Variant")]
public enum Variant : int
{
    [EnumMember]
    Rated = 1,
    [EnumMember]
    Actual = 2
}

Однако когда DeSerialize с использованием следующего кода выдает сообщение «Элемент с таким же ключом уже был добавлен». Есть идеи?

    public static T GetObject<T>(string xml) where T : class
    {
        T obj = null;
        using (var ms2 = new MemoryStream(GetBytes(xml)))
        {
            DataContractSerializer sr2 = new DataContractSerializer(typeof(T));
            obj = (T)sr2.ReadObject(ms2);
        }
        return obj;
    }

person daehaai    schedule 10.02.2014    source источник


Ответы (1)


Судя по давности вопроса, я предполагаю, что вы уже решили это, но сообщение об ошибке в исключении вводит в заблуждение: можно сериализовать и десериализовать словарь с ключом в перечислении. Проблема в том, что в вашем классе SystemData нет установщика для свойства словаря, частного или общедоступного. Таким образом, DataContractSerializer не имеет возможности сохранить информацию обратно в класс. Добавление частного установщика и запрет на чтение полей делает работу:

public class SystemData
{
    private double _ratedVoltage;
    private double _actualVoltage;

    #region ctor
    internal SystemData(
        double systemBaseMva,
        double ratedVoltage,
        double actualVoltage)
    {
        SystemBaseMVA = systemBaseMva;
        _ratedVoltage = ratedVoltage;
        _actualVoltage = actualVoltage;
    }
    #endregion

    #region Properties
    [DataMember]
    public double SystemBaseMVA { get; private set; }

    [DataMember]
    public Dictionary<Variant, double> Voltage
    {
        get
        {
            return new Dictionary<Variant, double>
            {
                {Variant.Rated, _ratedVoltage},
                {Variant.Actual, _actualVoltage}
            };
        }
        private set
        {
            double itemValue;
            if (value.TryGetValue(Variant.Rated, out itemValue))
                _ratedVoltage = itemValue;
            if (value.TryGetValue(Variant.Actual, out itemValue))
                _actualVoltage = itemValue;
        }
    }
    #endregion
}
person dbc    schedule 10.08.2014