Windows 8 C#ObservableCollection的序列化。获取错误:System.InvalidOperationException

时间:2013-01-24 08:39:59

标签: c# .net serialization windows-8 xml-serialization

我正在尝试序列化ObservableCollection。但我收到以下错误:请告诉我如何解决这个问题?

错误:

  

{System.InvalidOperationException:反映类型时出错   ' {System.Collections.ObjectModel.ObservableCollection {1}} 1.MoveNext()   在f:\ TFS \ New   TFS \ PDFReader \ Posh.PdfReader.Win8 \ ETEXT \ COMMON \ ApplicationSettings.cs:行   16   ---从抛出异常的先前位置开始的堆栈跟踪结束--- at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)在System.Runtime.CompilerServices.TaskAwaiter.GetResult()
  在eText.ViewModel.MainViewModel.d__a.MoveNext()中   F:\ TFS \新   TFS \ PDFReader \ Posh.PdfReader.Win8 \ ETEXT \视图模型\ MainViewModel.cs:行   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

BooksDownloadedData类

[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创建一个ObservableCollection,然后在序列化后将其保存在本地存储中,但在序列化时出现错误:

 /// <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; }
}

2 个答案:

答案 0 :(得分: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.

XmlSerializer类的limitations之一是被序列化的类必须具有无参数构造函数。

您是否可以使用DataContractSerializer

答案 1 :(得分:2)

问题在于Windows.Storage.StorageFile的使用,这显然不适合与序列化(或至少:不是XmlSerializer)。

可能能够重构您的模型,因此您无需使用StorageFile。您可能能够使用DownloadedBookFileDetails标记该成员([XmlIgnore]),并在反序列化后手动重新创建StorageFile。您可能能够使用不同的序列化程序(DataContractSerializer,JSON.NET,protobuf-net等)。

然而!在大多数情况下,我看到(并且我经常处理序列化)人们犯的关键错误是试图对抗序列化程序,以便他们可以继续使用现有的域模型。实际上,最简单要做的事情通常是:创建DTO :一个单独的模型,专门用于表示数据作为序列化的桥梁,然后映射到/来自DTO模型和您的主域模型。

这不仅每次非常容易,而且如果你想要的话,它也会让你处于非常有利的位置:

  • 修改域模型而不影响序列化数据(您只需调整映射)
  • 添加一个具有不同布局的单独版本/ API(可能是公共与私有API)
  • 使用不同的序列化程序(另外,或代替)