5

私は音楽メトロスタイルアプリを開発しています。何度も取得したくないので、オブジェクトmusic libraryを保存したいユーザーからすべての音楽ファイルを取得しています。これを行うには、オブジェクトをシリアル化してに保存してみました。ここここの例から、ファイル を生成しようとしましたが、XMLファイルの作成時に例外がスローされます。StorageFileStorageFileXMLXML

タイプ「Windows.Storage.StorageFile」はシリアル化できません。DataContractAttribute属性でマークを付け、シリアル化するすべてのメンバーをDataMemberAttribute属性でマークすることを検討してください。タイプがコレクションの場合は、CollectionDataContractAttributeでマークすることを検討してください。サポートされている他のタイプについては、Microsoft.NETFrameworkのドキュメントを参照してください。

これまでのところ、私のコードは以下のとおりです。

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.NETFrameworkのドキュメントを参照してください。では、どうすればシリアル化できますか?または、保存して再利用できる方法はありますか。私を助けてください

4

2 に答える 2

3

FutureAccessList http://msdn.microsoft.com/library/windows/apps/BR207457を利用すると、探している機能が提供されます。

パスを参照することにより、ファイルを取得してアクセスできます。これらのパスは、簡単に保存およびシリアル化できます(たとえば、リストとして)。

これにより、アプリでミュージックライブラリの外部にあるユーザーコンテンツにアクセスできるようにする場合に発生する可能性のある権限の問題も軽減されます。

于 2013-03-15T21:11:05.080 に答える
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();
}
于 2012-12-23T12:56:09.320 に答える