如何在WinRT(C#和XAML中的Metro应用程序)中序列化和deserliaze Dictionary ?

我一直试图解决这个愚蠢的问题几天了,它正在努力。我会很高兴有人有一个有效的例子,因为我到目前为止发现的那些没有用:(我可以序列化基本类型,但不是对象。我对DataContractAttribute等非常困惑。我得到的错误是:

{“类型’SerializeListWinRT.DataModel.LocalStorage + Cat’与数据合同名称’LocalStorage.Cat:http://schemas.datacontract.org/2004/07/SerializeListWinRT.DataModel’不是预期的。考虑使用DataContractResolver或添加任何静态地知道已知类型列表的类型 – 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。“}

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Storage; using System.IO; using System.Runtime.Serialization; using Windows.Storage.Streams; namespace SerializeListWinRT.DataModel { class LocalStorage { [DataContractAttribute] public class Cat { [DataMember()] public String Name { get; set; } } static private Dictionary _data = new Dictionary(); private const string filename = "items.xml"; static public Dictionary Data { get { return _data; } } static public T GetItem(string key) { T result = default(T); if (_data.ContainsKey(key)) { result = (T)_data[key]; } return result; } static public bool ContainsItem(string key) { return _data.ContainsKey(key); } static async public Task Save() { await Windows.System.Threading.ThreadPool.RunAsync((sender) => { LocalStorage.SaveAsync().Wait(); }, Windows.System.Threading.WorkItemPriority.Normal); } static async public Task Restore() { await Windows.System.Threading.ThreadPool.RunAsync((sender) => { LocalStorage.RestoreAsync().Wait(); }, Windows.System.Threading.WorkItemPriority.Normal); } static async private Task SaveAsync() { _data.Add("cat", new Cat { Name = "Myname is" }); _data.Add("dog", new Cat { Name = "Myname is" }); StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting); IRandomAccessStream sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite); IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0); DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(Dictionary)); sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data); await sessionOutputStream.FlushAsync(); } static async private Task RestoreAsync() { StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists); if (sessionFile == null) { return; } IInputStream sessionInputStream = await sessionFile.OpenReadAsync(); DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(Dictionary)); _data = (Dictionary)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead()); } } } 

我是怎么解决这个问题的:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Storage; using System.IO; using System.Runtime.Serialization; using Windows.Storage.Streams; namespace SerializeListWinRT.DataModel { class LocalStorage { [KnownType(typeof(SerializeListWinRT.Cat))] [DataContractAttribute] public class Cat { [DataMember()] public String Name { get; set; } } static private Dictionary _data = new Dictionary(); private const string filename = "ngt.xml"; static public Dictionary Data { get { return _data; } } static public T GetItem(string key) { T result = default(T); if (_data.ContainsKey(key)) { result = (T)_data[key]; } return result; } static public bool ContainsItem(string key) { return _data.ContainsKey(key); } static async public Task Save() { await Windows.System.Threading.ThreadPool.RunAsync((sender) => { LocalStorage.SaveAsync().Wait(); }, Windows.System.Threading.WorkItemPriority.Normal); } static async public Task Restore() { await Windows.System.Threading.ThreadPool.RunAsync((sender) => { LocalStorage.RestoreAsync().Wait(); }, Windows.System.Threading.WorkItemPriority.Normal); } static async private Task SaveAsync() { _data.Add("cat", new Cat { Name = "Myname is" }); _data.Add("dog", new Cat { Name = "Myname is" }); StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting); IRandomAccessStream sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite); IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0); DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(Dictionary), new Type[] { typeof(T) }); sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data); await sessionOutputStream.FlushAsync(); } static async private Task RestoreAsync() { StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists); if (sessionFile == null) { return; } IInputStream sessionInputStream = await sessionFile.OpenReadAsync(); DataContractSerializer sessionSerializer = new DataContractSerializer(typeof(Dictionary), new Type[] { typeof(T) }); _data = (Dictionary)sessionSerializer.ReadObject(sessionInputStream.AsStreamForRead()); } } 

}

我通过添加KnownType属性解决了这个问题

  [KnownType(typeof(SerializeListWinRT.Cat))] 

但我之前不必这样做,所以我不确定它是否与WinRT相关的问题。 哦,它现在确实有效,但我仍然很好奇为什么你必须使用KnownType属性进行装饰。