使用XmlSerializer

时间:2017-01-05 10:23:03

标签: c# com xmlserializer

我在班上得到了这个:

namespace MSAToolsLibrary.PublisherEntry
{
    [XmlRoot(ElementName = "PublisherDatabase", Namespace = "http://www.publictalksoftware.co.uk/msa")]
    public class PublisherData
    {
        public PublisherData()
        {
            //_Publishers = new List<Publisher>();
            _PublishersDictionary = new Dictionary<string, Publisher>();
        }

        public List<Publisher> Publishers
        {
            get { return _PublishersDictionary.Select(x => x.Value).ToList(); }
            set { _PublishersDictionary = value.ToDictionary(x => x.Name, x => x); }
        }
        private Dictionary<string, Publisher> _PublishersDictionary;

        [XmlIgnore]
        public Dictionary<string, Publisher> PublisherDictionary
        {
            get { return _PublishersDictionary; }
        }


        public void AddPublisher(String strName, String strNotes, Gender eGender, Appointed eAppointedAs, Serving eServingAs, bool bUseForDemonstrations, bool bAvailableMidweek, bool bAvailableWeekend, DateTime[] listDatesNotAvailable)
        {
            Publisher _Publisher = new Publisher()
            {
                Name = strName,
                Notes = strNotes,
                Gender = eGender,
                AppointedAs = eAppointedAs,
                ServingAs = eServingAs,
            };

            _Publisher.Assignments.UseForDemonstrations = bUseForDemonstrations;
            _Publisher.Availability.Midweek = bAvailableMidweek;
            _Publisher.Availability.Weekend = bAvailableWeekend;
            _Publisher.Availability.DatesNotAvailable = new List<DateTime>(listDatesNotAvailable);

            //_Publishers.Add(_Publisher);
            _PublishersDictionary.Add(strName, _Publisher);
        }
    }
}

现在,当我将数据保存到XML时,一切正常。

但是当我读到时:

public void ReadPublisherData(out Int64 iResult)
{
    _PublisherData.Publishers.Clear(); // Reset

    iResult = MakeResult(true);

    try
    {
        XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
        using (StreamReader reader = new StreamReader(_strPathXML))
        {
            _PublisherData = (PublisherData)x.Deserialize(reader);
            iResult = _PublisherData.PublisherDictionary.Count;
        }
    }
    catch
    {
        iResult = MakeResult(false);
    }
 }

不起作用。我在列表或字典中没有发布者。

我做错了什么?

更新

如果我更改PublisherData声明,使其具有所需的后退字段:

public PublisherData()
{
    _Publishers = new List<Publisher>();
    _PublishersDictionary = new Dictionary<string, Publisher>();
}

public List<Publisher> Publishers
{
    get => _Publishers; set => _Publishers = value;
}
private List<Publisher> _Publishers;

然后这会导致数据正确序列化,并且我得到了MFC应用程序中的预期。但是现在我的PublisherDictionary正悬而未决。所以我添加了一个函数:

   public void BuildPublisherDictionary()
    {
        _PublishersDictionary = _Publishers.ToDictionary(x => x.Name, x => x);
    }

并调整了阅读程序:

   public void ReadPublisherData(out Int64 iResult)
    {
        iResult = MakeResult(true);

        try
        {
            _PublisherData.Publishers.Clear(); // Reset

            XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
            using (StreamReader reader = new StreamReader(_strPathXML))
            {
                _PublisherData = (PublisherData)x.Deserialize(reader);

                _PublisherData.BuildPublisherDictionary();
                iResult = _PublisherData.PublisherDictionary.Count;
            }
        }
        catch
        {
            iResult = MakeResult(false);
        }
     }

有效。但我不知道这是否是最简单的方法。我上面的问题是列表/字典现在彼此分离。因此,如果我将一个发布者添加到字典中,它现在将不在列表中。

更新2

目前,在读取XML后,如果我添加或删除发布者,我将其应用于列表和字典。除非有更简单的方法。

1 个答案:

答案 0 :(得分:1)

序列化程序只会调用List的getter,然后为它找到的每个元素调用Add,为它提供从该元素反序列化的类型的实例。

如果您的要求是同时拥有列表和字典,则必须提供类型的实现,并实现适用的接口。

以下ListDict使用List和Dictionary作为其后备存储,同时实现在(de)序列化中使用的IList。

public class ListDict<K, T>:IList<T>
{

   public Dictionary<K, T> dict = new Dictionary<K, T>();
   public List<T> list = new List<T>();
   Func<T,K> KeyFunc;

   // takes an Function that returns a key for T
   public ListDict(Func<T,K> keyfunc) 
   {
      KeyFunc = keyfunc;
   } 

   // called by the serializer
   public void Add(T value) 
   {
      Add( KeyFunc(value), value);
   }

   // fill both List and Dictionary
   public void Add(K key, T value) 
   {
      list.Add(value);
      dict.Add( key , value);
   }
   // left out other required methods from IList<T>
}

现在,您的PublisherData类将按如下方式更改以利用上述类:

[XmlRoot(ElementName = "PublisherDatabase", Namespace = "http://www.publictalksoftware.co.uk/msa")]
public class PublisherData
{
    private ListDict<string, Publisher> _PublishersDictionary;
    public PublisherData()
    {
        // provide the function to generate a key for a Publisher
        _PublishersDictionary = new ListDict<string,Publisher>( (p) => p.Name  );   
    }

    [XmlElement]
    public ListDict<string,Publisher> Publishers
    { 
        get { return _PublishersDictionary; }
    }


    [XmlIgnore]
    public Dictionary<string, Publisher> PublisherDictionary
    {
        get {return _PublishersDictionary.dict; }
    }
}

使用上面的类在反序列化后直接给我一个填充列表和Dictionary。您必须确保在ListDict中保持后备存储同步。也许你可以没有它,但这取决于你的确切用例。