Windows 8 C# Serialization of ObservableCollection.获取错误:系统无效

本文关键字:取错误 系统 无效 获取 ObservableCollection Serialization of Windows | 更新日期: 2023-09-27 17:56:01

我正在尝试序列化一个可观察的集合。但是我收到以下错误:让我知道如何解决此问题?

错误:

{System.InvalidOperationException: 有一个反映类型的错误 'System.Collections.ObjectModel.ObservableCollection 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
1.MoveNext() 在 f:''TFS''New 中 TFS''PDFReader''Posh.PdfReader.Win8''eText''Common''ApplicationSettings.cs:line 16 --- 从引发异常的先前位置的堆栈跟踪结束 --- System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at 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}

我用来序列化的代码:

图书类:

[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    
}

书籍下载数据类

 /// <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创建了一个可观察集合,然后在序列化后将其保存在本地存储中,但在序列化时出现错误:

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

Windows 8 C# Serialization of ObservableCollection.获取错误:系统无效

从您的堆栈跟踪中,我看到:

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类的限制之一是要序列化的类必须具有无参数构造函数。

您可以改用DataContractSerializer吗?

问题是 Windows.Storage.StorageFile 的使用,这显然不是为了很好地与序列化配合(或者至少:不是XmlSerializer)。

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

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

这不仅每次都非常容易地工作,而且如果您愿意,还可以使您处于非常有利的位置:

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