如何在Metro应用程序中序列化Windows.Storage.StorageFile

5
我正在开发一款音乐地铁风格的应用程序。我从用户的音乐库中获取所有音乐文件,我想存储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);

它触发了一个异常,并显示:

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


object musicStorageFile的类型是什么?显然最终的对象是导致错误的原因。如果它是音乐文件,则无法使用XML序列化它。 - Ucodia
感谢您的评论Ucodia,musicStorageFile是音乐文件,我是否有其他方法可以实现上述功能,例如存储音乐文件或者将StorageFile对象(音乐文件)存储在SQLite 3中,敬请回复。 - Raj Kumar
音乐文件已经是文件了,所以试图将它们序列化到一个文件中听起来对我来说有点过度。不过我仍然会提供一个解决方案。 - Ucodia
2个回答

3
利用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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接