【问题标题】:How to serialize Windows.Storage.StorageFile in metro app如何在 Metro 应用程序中序列化 Windows.Storage.StorageFile
【发布时间】:2012-12-23 09:45:29
【问题描述】:

我正在开发一个音乐地铁风格的应用程序。我从用户music library 获取所有音乐文件我想存储StorageFile 对象,因为我不想一次又一次地检索。为此,我尝试序列化StorageFile 对象并将其存储到XML .从示例herehere 我尝试生成XML 文件,但它在创建XML 文件时抛出异常

无法序列化类型“Windows.Storage.StorageFile”。考虑使用 DataContractAttribute 属性对其进行标记,并使用 DataMemberAttribute 属性标记您想要序列化的所有成员。如果类型是集合,请考虑使用 CollectionDataContractAttribute 对其进行标记。有关其他支持的类型,请参阅 Microsoft .NET Framework 文档。

到目前为止,我的代码如下,

namespace CloudMusic.AppSettings
{
    [KnownType(typeof(CloudMusic.AppSettings.MusicFileDict))]
    [DataContractAttribute]
    public class MusicFileDict
    {
        [DataMember]
        public object musicStorageFile { get; set; }

        [DataMember]
        public int id { get; set; }
    }
}

从下面的类我生成XML

class GenerateMusicDict
{    
        private const string filename = "musiclist.xml";
        static private List<MusicFileDict> _data = new List<MusicFileDict>();

        static public List<MusicFileDict> Data
        {
            get { return _data; }
        }
        static async public Task Save<T>()
        {
            await Windows.System.Threading.ThreadPool.RunAsync((sender) => GenerateMusicDict.SaveAsync<T>().Wait(), Windows.System.Threading.WorkItemPriority.Normal);
        }        

        internal static async Task SaveAsync<T>()
        {           
            GenerateMusicDict.GenerateMusicFileDict();           
            try
            {
                StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                IRandomAccessStream sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite);
                IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0);

                var sessionSerializer = new DataContractSerializer(typeof(List<MusicFileDict>), new Type[] { typeof(T) });
                sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data);
                await sessionOutputStream.FlushAsync();
            }
            catch (Exception)
            {
            }

        }
        /// <summary>
        /// Generate music file dictonary according to songs ID
        /// </summary>
        /// <param name="musicFileList"></param>
        private static void GenerateMusicFileDict()
        {
            List<StorageFile> music_file_list = MusicFileDict.GetMusicList(); // At this stage i'll get all my music files,GetMusicList() function returns List<StorageFile>
            for (int i = 0; i < music_file_list.Count; i++)
            {
                _data.Add(new MusicFileDict { id = i, musicStorageFile = music_file_list[i]});          
            } 
        }
}

并从我的主类调用 Save 方法使用

 await GenerateMusicDict.Save<MusicFileDict>(); 

在这一行的 SaveAsync() 函数

 sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data);

它正在发出 Exception 的说法

无法序列化类型“Windows.Storage.StorageFile”。考虑使用 DataContractAttribute 属性对其进行标记,并使用 DataMemberAttribute 属性标记您想要序列化的所有成员。如果类型是集合,请考虑使用 CollectionDataContractAttribute 对其进行标记。有关其他支持的类型,请参阅 Microsoft .NET Framework 文档。 那么我该如何序列化呢?或者有什么方法可以存储和重复使用。请帮帮我

【问题讨论】:

  • object musicStorageFile的类型是什么?显然,最终对象是导致错误的对象。如果是音乐文件,不能用 XML 序列化。
  • 感谢 Ucodia 的评论,musicStorageFile 是音乐文件,有没有其他方法可以实现上述功能,比如存储音乐文件或者是否可以在 SQLite 中存储 StorageFile 对象(音乐文件) 3、请回复。
  • 音乐文件已经是......嗯......文件,所以尝试将它们序列化到一个文件中对我来说听起来有点矫枉过正。我还是会用解决方案来回答。

标签: c# windows-8 xml-serialization microsoft-metro windows-runtime


【解决方案1】:

利用 FutureAccessList http://msdn.microsoft.com/library/windows/apps/BR207457 它应该提供您正在寻找的功能。

您可以通过引用文件的路径来检索和访问文件。这些路径可以轻松存储和序列化(例如作为列表)。

如果您希望您的应用能够访问音乐库之外的用户内容,这也可以缓解您可能遇到的任何权限问题。

【讨论】:

    【解决方案2】:

    显然,从您的代码来看,您似乎正试图在另一个文件中序列化一个音乐文件,这有点矫枉过正。因此,与其尝试序列化音乐,不如使用 URI 对其进行引用。

    [DataContractAttribute]
    public class MusicFileDict
    {
        [DataMember]
        public Uri MusicFileUri { get; set; }
    
        [DataMember]
        public int Id { get; set; }
    }
    

    然后像这样创建你的对象

    private static void GenerateMusicFileDict()
    {
         List<StorageFile> music_file_list = MusicFileDict.GetMusicList(); 
         for (int i = 0; i < music_file_list.Count; i++)
         {
              StorageFile currentFile = music_file_list[i];
    
              _data.Add(new MusicFileDict 
                        { 
                            Id = i,
                            MusicFileUri = new Uri(currentFile.Path)
                        });          
         } 
    }
    

    如果您需要保留对您可以管理的音乐文件的引用,您可以将音乐文件复制到本地文件夹并改为引用此 URI 路径。但请记住,音乐文件可能很重,而且存储空间可能很宝贵,尤其是在 WinRT 设备上。

    另外,请关闭您的信息流!

    IRandomAccessStream sessionRandomAccess = null;
    
    try
    {
        StorageFile sessionFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
        sessionRandomAccess = await sessionFile.OpenAsync(FileAccessMode.ReadWrite);
        IOutputStream sessionOutputStream = sessionRandomAccess.GetOutputStreamAt(0);
    
        var sessionSerializer = new DataContractSerializer(typeof(List<MusicFileDict>), new Type[] { typeof(T) });
        sessionSerializer.WriteObject(sessionOutputStream.AsStreamForWrite(), _data);
        await sessionOutputStream.FlushAsync();
    }
    catch (Exception)
    {
    }
    finally
    {
        sessionRandomAccess.Dispose();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多