2

ObservableCollection をシリアライズしようとしています。しかし、次のエラーが表示されます: Let me know how can I fix this?

エラー:

{System.InvalidOperationException: タイプ 'System.Collections.ObjectModel.ObservableCollection 1.MoveNext() を f:\TFS\New TFS\PDFReader\Posh.PdfReader.Win8\eText\Common\ApplicationSettings.cs:line に反映するエラーが発生しました16 --- 例外がスローされた前の場所からのスタック トレースの終了 --- System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) で System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) で System.Runtime .CompilerServices.TaskAwaiter.GetResult() at eText.ViewModel.MainViewModel.d__a.MoveNext() in f:\TFS\New TFS\PDFReader\Posh.PdfReader.Win8\eText\ViewModel\MainViewModel.cs:line 268}1[eText.DataModel.BooksDownloadedData]'. ---> System.InvalidOperationException: There was an error reflecting type 'eText.DataModel.BooksDownloadedData'. ---> System.InvalidOperationException: Cannot serialize member 'eText.DataModel.BooksDownloadedData.DownloadedBookFileDetails' of type 'Windows.Storage.StorageFile', see inner exception for more details. ---> System.InvalidOperationException: Windows.Storage.StorageFile cannot be serialized because it does not have a parameterless constructor. --- End of inner exception stack trace --- at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type) at System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo) at System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo) at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) --- End of inner exception stack trace --- at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.CreateArrayElementsFromAttributes(ArrayMapping arrayMapping, XmlArrayItemAttributes attributes, Type arrayElementType, String arrayElementNs, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportArrayLikeMapping(ArrayModel model, String ns, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) --- End of inner exception stack trace --- at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type) at eText.Common.Xml.Serialize[T](Object obj, Type[] extraTypes) in f:\TFS\New TFS\PDFReader\Posh.PdfReader.Win8\eText\Common\Utility.cs:line 81
at eText.Common.ApplicationSettings.<SaveDataToFileAsync>d__0

シリアル化に使用しているコード:

書籍クラス:

[DataContract] 
public class Book : ViewModelBase
{
    #region Constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="Book" /> class.
    /// </summary>
    public Book(){}

    /// <summary>
    /// Initializes a new instance of the <see cref="Book" /> class.
    /// </summary>
    /// <param name="BookTitle">The book title.</param>
    /// <param name="BookCategory">The book category.</param>
    /// <param name="DownloadURL">The download URL.</param>
    /// <param name="TotalNumberOfPages">The total number of pages.</param>
    /// <param name="BookAuthor">The book author.</param>
    /// <param name="ImageURL">The image URL.</param>
    public Book(string BookTitle,string BookCategory,string DownloadURL, string TotalNumberOfPages, string BookAuthor, string ImageURL)
    {
        this.BookCategory = BookCategory;
        this.BookTitle = BookTitle;
        this.BookAuthor = BookAuthor;
        this.TotalNumberOfPages = TotalNumberOfPages;
        this.DownloadURL = DownloadURL;
        this.ImageURL = ImageURL;
    }

    #endregion    
}

BooksDownloadedData クラス

 /// <summary>
    /// Class to store downloaded books metaData
    /// </summary>
    [DataContract] 
    public class BooksDownloadedData
    {

        /// <summary>
        /// The downloaded books detail
        /// </summary>
        [DataMember]
        public Book DownloadedBooks { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is downloaded completed.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is downloaded completed; otherwise, <c>false</c>.
        /// </value>
       [DataMember]
        public bool IsDownloadedCompleted { get; set; }
}

BooksDownloadedData の ObservableCollection を作成し、シリアル化後にローカル ストレージに保存しましたが、シリアル化時にエラーが発生しました。

// Create object to get the saved meta data of files
  ObservableCollection<BooksDownloadedData> downLoadedFiles;

 // Save the data to the local storage
                await ApplicationSettings.SaveDataToFileAsync<ObservableCollection<BooksDownloadedData>>(fileName, downLoadedFiles);

 public static async Task SaveDataToFileAsync<T>(string key, T value, bool roaming = false, Type[] extraTypes = null)
        {
            var file = roaming ? await ApplicationData.Current.RoamingFolder.CreateFileAsync(key + ".xml", CreationCollisionOption.ReplaceExisting) :
                await ApplicationData.Current.LocalFolder.CreateFileAsync(key + ".xml", CreationCollisionOption.ReplaceExisting);

            var xml = Xml.Serialize<T>(value, extraTypes);
            await FileIO.WriteTextAsync(file, xml, UnicodeEncoding.Utf8);
        }

 public static string Serialize<T>(object obj, Type[] extraTypes = null)
        {
            using (var sw = new StringWriter())
            {
                var serializer = extraTypes == null ? new XmlSerializer(typeof(T)) : new XmlSerializer(typeof(T), extraTypes);
                serializer.Serialize(sw, obj);
                return sw.ToString();
            }
        }
4

2 に答える 2

3

あなたのスタックトレースから私は見る:

Cannot serialize member 'eText.DataModel.BooksDownloadedData.DownloadedBookFileDetails' of type 'Windows.Storage.StorageFile', see inner exception for more details. ---> System.InvalidOperationException: Windows.Storage.StorageFile cannot be serialized because it does not have a parameterless constructor.

クラスの制限の1 つは、XmlSerializerシリアル化されるクラスがパラメーターなしのコンストラクターを持たなければならないことです。

代わりに使えますDataContractSerializerか?

于 2013-01-24T09:00:45.800 に答える
2

問題は、の使用ですWindows.Storage.StorageFile。これは明らかに、シリアル化でうまく機能することを意図したものではありません(または少なくとも:そうではありませんXmlSerializer)。

を使用する必要ないように、モデルをリファクタリングできる場合がありますStorageFile。そのメンバー( )に。のマークを付け、逆シリアル化後に手動で再作成できる場合があります。別のシリアライザー( 、JSON.NET、protobuf-netなど)を使用できる場合があります。DownloadedBookFileDetails[XmlIgnore]StorageFileDataContractSerializer

でも!ほとんどの場合、私は(そして私はシリアル化をよく扱っていますが)人々が犯す主な間違いは、既存のドメインモデルを使い続けることができるようにシリアライザーと戦おうとしていることです。実際には、通常、最も簡単な方法は次のとおりです。DTOを作成する:シリアル化へのブリッジとしてデータを表すためだけに設計された別のモデルを作成し、DTOモデルとメインドメインモデルとの間でマッピングします。

これは毎回本当に簡単に機能するだけでなく、次のことをしたい場合は非常に強力な立場になります。

  • シリアル化されたデータに影響を与えずにドメインモデルを修正します(マッピングを微調整するだけです)
  • レイアウトが異なる別のバージョン/APIを追加します(パブリックAPIとプライベートAPIなど)
  • 別のシリアライザーを使用する(さらに、または代わりに)
于 2013-01-24T09:06:37.137 に答える