无法使用XmlSerializer读取XML内容 [英] Failing to read XML content using XmlSerializer

查看:59
本文介绍了无法使用XmlSerializer读取XML内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在班上得到这个:

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都很好用。

Now, when I save my data to XML it all works good.

但是当我读入:

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);
    }
 }

不起作用。我的列表或词典中的出版商为零。

Doesn't work. I have zero publishers in the list or the dictionary.

我在做什么错了?

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

If I change the PublisherData declaration so that it has the needed back field:

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 正在挂起。因此我添加了一个函数:

Then this causes the data to serialize correctly and I get what is expected in the MFC application. But now my PublisherDictionary is hanging. So I added a function:

   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);
        }
     }

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

It works. But I don't know if that is the simplest way. My problem with the above is that the list / dictionary are now detached from each other. So if I add a publisher to the dictionary it will now not be in the list.

目前,在阅读XML之后,如果我添加或删除了Publisher,我会将其同时应用于列表和字典。除非有更简单的方法。

At the moment, after reading in the XML, if I add or remove a Publisher I am applying it to both the list and the dictionary. Unless there is a simpler way.

推荐答案

序列化程序将仅调用列表的getter,然后调用为找到的每个元素添加,为其提供从该元素反序列化的类型的实例。

The serializer will only call the getter of your List and then call Add for each element it finds, providing it the instance of the type it deserialized from that element.

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

If your requirement is to have both a list and a dictionary you'll have to provide an implementation of an type that does so and implements an applicable interface.

以下ListDict在实现要在反序列化中使用的IList时,将List和Dictionary作为其后备存储。

The following ListDict uses a List and a Dictionary as their backing stores while implementing IList to be used in the (de)serializtion.

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类将进行如下更改以利用上述类:

Now your PublisherData class will change as follows to leverage above class:

[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; }
    }
}

使用以上课程为我提供了一个完整的列表和字典反序列化后直接进行。当然,您必须确保将后备存储在ListDict中保持同步。也许您可以不用它,但这取决于您的确切用例。

Using above classes gives me a filled list and Dictionary directly after deserialization. You'll have to make sure of course to keep the backing stores in sync in the ListDict. Maybe you can do without it but that depends on your exact usecase.

这篇关于无法使用XmlSerializer读取XML内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆