Windows Phone 7中的DataContractSerializer问题

时间:2010-11-04 00:42:47

标签: serialization windows-phone-7

这种情况有时只会发生,但会使我的文件无法读取。问题是DataContractSerializer添加了几个>>>在序列化时在XML文件的末尾。在尝试反序列化时使它们无用。有谁有这个问题?例如:

<SomeObject xmlns="someNamespace">
</SomeObject>>>

感谢。

编辑:

其实不,那不是问题。这次文件很好,这就是它的样子:

<FavoriteClubManager xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/TicketingWP7.Preferences">
 <FavoriteClubs xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <d2p1:KeyValueOfstringboolean>
   <d2p1:Key>XXX</d2p1:Key>
   <d2p1:Value>true</d2p1:Value>
  </d2p1:KeyValueOfstringboolean>
 </FavoriteClubs>
</FavoriteClubManager>

这是我在尝试反序列化时遇到的错误:

“反序列化TicketingWP7.Preferences.FavoriteClubManager类型的对象时出错。根元素丢失。”

但是我没有看到该文件有什么问题。

代码

保存:

using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
    try
    {
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Create, file))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(FavoriteClubManager));

            serializer.WriteObject(stream, this);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("There was an error saving your favorite clubs. " + ex.Message);
    }
}

装载:

using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
    if (file.FileExists(_fileName))
    {
        try
        {
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Open, file))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(FavoriteClubManager));

                FavoriteClubManager temp = serializer.ReadObject(stream) as FavoriteClubManager;

                stream.Close();
            }

            _isLoaded = true;
        }
        catch (Exception ex)
        {
            MessageBox.Show("There was an error loading your favorite clubs. " + ex.Message);
        }
    }
}

2 个答案:

答案 0 :(得分:4)

问题实际上是这样的:

  1. 您将对象序列化一次,然后将其保存到隔离存储中。
  2. 您从隔离存储中读取对象并对其进行反序列化。
  3. 然后更新对象并对其进行重新序列化,然后再次保存。
  4. 您从隔离存储中读取它,并且由于额外的字符而无法反序列化。
  5. 如果这是重新创建问题的流程,我怀疑后续保存的seializations是一个稍小的对象,因此创建一个小于先前写入的序列化字符串。
    保存后面的字符串时,它会写在先前保存的字符串之上,旧字符串的末尾仍然保留在那里。

    解决方案是确保在保存新内容之前删除现有文件或删除其内容。

    我之前遇到过类似的问题,发现它很痛苦。

    顺便说一句。您可能还想重新考虑有关性能的序列化策略。有关详细信息,请查看this blog post by Kevin Marshall

答案 1 :(得分:0)

解决了它。几乎被骗了。我基本上使用XDocument读取XML文档,使读者使用XDocument.CreateReader()并将读者传递给DataContractSerializer。这就是诀窍,我知道它不是很优雅,但它是一个解决方案。希望我将来会提出更好的解决方案。现在,这是代码:

private bool Load()
{
    if (!_isLoaded)
    {
        using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (file.FileExists(_fileName))
            {
                string text = string.Empty;

                try
                {
                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(_fileName, FileMode.Open, file))
                    {
                        if (stream.Length > 0)
                        {
                            XDocument document = GetXDocument(stream);

                            DataContractSerializer serializer = new DataContractSerializer(typeof(ClubManager));

                            ClubManager temp = serializer.ReadObject(document.CreateReader()) as ClubManager;

                            stream.Close();
                        }
                    }

                    _isLoaded = true;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("There was an error loading your favorite clubs. " + ex.Message);
                }
            }
        }
    }

    return _isLoaded;
}

private XDocument GetXDocument(IsolatedStorageFileStream stream)
{
    // read the file to find errors
    string documentText = ReadBytes(stream);

    return XDocument.Parse(documentText);
}

private static string ReadBytes(IsolatedStorageFileStream stream)
{
    byte[] buffer = new byte[stream.Length];

    stream.Read(buffer, 0, buffer.Length);

    string normal = string.Empty;
    string hex = BitConverter.ToString(buffer).Replace("-", "");

    while (hex.Length > 0)
    {
        // Use ToChar() to convert each ASCII value (two hex digits) to the actual character
        normal += System.Convert.ToChar(System.Convert.ToUInt32(hex.Substring(0, 2), 16)).ToString();
        // Remove from the hex object the converted value
        hex = hex.Substring(2, hex.Length - 2);
    }

    return normal;
}

谢谢!