我正在尝试使用这段代码将数据写入文件;
public async Task<bool> WriteDataAsync<T>(T data, string fileName, string folderPath)
{
try
{
var store = await GetFolder(folderPath);
using (MemoryStream sessionData = new MemoryStream())
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(sessionData, data);
StorageFile sessionFile = await store.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream fileStream = await sessionFile.OpenStreamForWriteAsync())
{
sessionData.Seek(0, SeekOrigin.Begin);
await sessionData.CopyToAsync(fileStream);
await fileStream.FlushAsync();
}
}
}
很长一段时间它工作正常,但后来我得到了这个异常;
键入“Microsoft.Practices.Prism.PubSubEvents.EventAggregator”和数据协定名称“EventAggregator:http://schemas.datacontract.org/2004/07/Microsoft.Practices.Prism.PubSubEvents” ' 不是预期的。如果您正在使用 DataContractSerializer 或将任何静态未知类型添加到已知类型列表中,请考虑使用 DataContractResolver - 例如,通过使用 KnownTypeAttribute 属性或将它们添加到传递给序列化程序的已知类型列表中。
所以我查看了 DataContractResolver,并在 MSDN 中找到了这个页面;
https://msdn.microsoft.com/en-us/library/ee358759(v=vs.110).aspx
我创建了代码来修复我的错误;
public class LogResolver : DataContractResolver
{
public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
if (dataContractType != typeof(LogViewModel))
{
return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName,
out typeNamespace);
}
var dictionary = new XmlDictionary();
typeName = dictionary.Add("Log");
typeNamespace = dictionary.Add("http://tempuri.com");
return true;
}
public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
{
if (typeName == "Log" && typeNamespace == "http://tempuri.com")
{
return typeof(LogViewModel);
}
return knownTypeResolver.ResolveName(typeName, typeNamespace, null, null);
}
}
和
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
if (typeof(T).Name == "LogViewModel")
{
var writer = XmlDictionaryWriter.CreateDictionaryWriter(XmlWriter.Create(sessionData));
serializer.WriteObject(writer, data, new LogResolver());
}
else
{
serializer.WriteObject(sessionData, data);
}
但现在我的代码将无法编译,因为 serializer.WriteObject 方法没有采用 3 个参数。 怎么会这样? MSDN 肯定不会错吧?
编辑 我决定查看 WriteObject 所在的序列化类的定义,我发现了这一点;
// Decompiled with JetBrains decompiler
// Type: System.Runtime.Serialization.XmlObjectSerializer
// Assembly: System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// MVID: 94FDD0A8-CB5D-4815-A53D-5DC4F6C5FA80
// Assembly location: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\Profile\Profile32\System.Runtime.Serialization.Xml.dll
using System.IO;
using System.Xml;
namespace System.Runtime.Serialization
{
public abstract class XmlObjectSerializer
{
protected XmlObjectSerializer();
public abstract bool IsStartObject(XmlDictionaryReader reader);
public virtual bool IsStartObject(XmlReader reader);
public virtual object ReadObject(Stream stream);
public virtual object ReadObject(XmlDictionaryReader reader);
public abstract object ReadObject(XmlDictionaryReader reader, bool verifyObjectName);
public virtual object ReadObject(XmlReader reader);
public virtual object ReadObject(XmlReader reader, bool verifyObjectName);
public abstract void WriteEndObject(XmlDictionaryWriter writer);
public virtual void WriteEndObject(XmlWriter writer);
public virtual void WriteObject(Stream stream, object graph);
public virtual void WriteObject(XmlDictionaryWriter writer, object graph);
public virtual void WriteObject(XmlWriter writer, object graph);
public abstract void WriteObjectContent(XmlDictionaryWriter writer, object graph);
public virtual void WriteObjectContent(XmlWriter writer, object graph);
public abstract void WriteStartObject(XmlDictionaryWriter writer, object graph);
public virtual void WriteStartObject(XmlWriter writer, object graph);
}
}
因此没有使用 DataContractResolver 的 WriteObject 方法。那我该怎么办呢?
编辑 - 解决方法不是解决方案。 如果您查看错误消息,问题是正在写入的对象包含无法序列化的事件。 此事件在所有 ViewModel 中使用的 BaseViewModel 类中定义。所以我创建了一个新的基类,仅供那些需要它的 ViewModels 使用,如下所示; 命名空间 M.Survey.UILogic.ViewModels { 使用 M.Survey.UILogic.Helpers; 使用 Microsoft.Practices.Prism.PubSubEvents;
public class BaseEventViewModel : BaseViewModel
{
public BaseEventViewModel()
{
this.EventAgg = EventAggHolder.EventAgg;
}
public IEventAggregator EventAgg { get; set; }
}
所以我的问题现在已经解决了。但是它没有解决如何编写包含事件的对象的问题。在 WinRT 中,我无法找到可以将导致此错误的事件从序列化中排除的属性。
最佳答案
我怀疑 WinRT 不支持此 WriteObject 重载。您可以尝试以下替代方案。
使用DataContractSerializerSettings 设置DataContractResolver,然后将设置对象传递给DataContractSerializer 构造函数。然后serializer.WriteObject(writer, data)就可以照常使用了。
DataContractSerializerSettings settings = new DataContractSerializerSettings(); settings.DataContractResolver = new LogResolver(); DataContractSerializer serializer = new DataContractSerializer(typeof(T), settings);
使用 KnownType用于指定序列化程序要检测的已知类型列表的属性。
希望这对您的场景有所帮助!
编辑:由于问题在于正在序列化不需要的属性,因此使用 IgnoreDataMember将指示序列化程序将其从序列化中排除。
关于C#使用DataContractResolver向文件写入数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42575213/