我正在重构我的XML序列化,并认为我会尝试使用DataContractSerializer。 一切都顺利进行,直到需要序列化这个类:
using System;
using System.Runtime.Serialization;
namespace VDB_Sync.Model
{
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
{
[DataMember]
private MySqlDbType mydataType;
[DataMember]
private object value;
public Konstant(string navn, MySqlDbType dataType, object value)
: base(navn, dataType, "*Konstant", false, false)
{
//this.navn = navn;
this.mydataType = dataType;
this.value = value;
if (navn.Contains("*Løbenummer"))
{
navn = "*Konstant: " + Convert.ToString(value);
}
}
public object Value
{
get
{
return value;
}
}
}
}
它给了我这个:
输入数据合约名称为“Konstant:http://schemas.datacontract.org/2004/07/VDB_Sync.Model”的“VDB_Sync.Model.Konstant”不是预期的。考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 - 例如,使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。
*到目前为止我找到的帮助指向了集合和类型。我的类中有一个枚举(MySqlDbType) - 但得到这个:当我没有声明DataMembers时,我甚至得到了同样的错误:-x 那么 - 这里发生了什么?我错过了什么?
供参考,这是我如何序列化它,VDB_SessionController是根:*
public void GemKonfig(VDB_SessionController session)
{
var settings = new XmlWriterSettings()
{
Indent = true,
IndentChars = "\t"
};
var writer = XmlWriter.Create(defaultFile, settings);
DataContractSerializer ser =
new DataContractSerializer(typeof(VDB_SessionController));
ser.WriteObject(writer, session);
writer.Close();
}
答案 0 :(得分:63)
报告的异常是针对VDB_Sync.Model.Konstant。这意味着在链的某个地方,这个类被引入另一个类,该类是被序列化的类。
问题在于,根据Konstant在此类中的嵌入方式(例如,如果它位于集合或通用列表中),DataContractSerializer可能无法在反序列化期间为其外观做好准备。
要解决此问题,您需要将known-type属性应用于包含Konstant的类。根据您的序列化代码,我怀疑这是VDB_SessionController
。
因此,尝试使用KnownType属性装饰此类:
[KnownType(typeof(VDB_Sync.Model.Konstant)]
public class VDB_SessionController
答案 1 :(得分:15)
将此添加到WebApiConfig.cs
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
答案 2 :(得分:13)
您还可以将[KnownType]
和反射结合起来,使您的代码更能抵御未来的变化。
[DataContract]
[KnownType("GetKnownPersonTypes")]
internal class Person
{
private static IEnumerable<Type> _personTypes;
private static IEnumerable<Type> GetKnownTypes()
{
if (_personTypes == null)
_personTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => typeof (Person).IsAssignableFrom(t))
.ToList();
return _personTypes;
}
}
现在DataContractSerializer
/ DataContractJsonSerializer
/ XmlSerializer
配置为使用Person
,也可以使用从{{1>派生的任何类型(只要它在同一个程序集中声明)。
答案 3 :(得分:4)
使用KnownTypeAttribute解析DataFelt类。 见:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx
答案 4 :(得分:4)
我遇到的问题是我从WebAPI控制器返回界面(IIndividual)。当我将该返回类型更改为Class(Individual)类型时,此错误消失了。
不工作:
[HttpGet]
[Route("api/v1/Individual/Get/{id}")]
public IIndividual Get([FromUri]int id)
{
return _individualService.Get(id);
}
工作:
[HttpGet]
[Route("api/v1/Individual/Get/{id}")]
public Individual Get([FromUri]int id)
{
IIndividual individual = _individualService.Get(id);
return individual as Individual;
}
答案 5 :(得分:3)
就像@Leon建议的那样,但是来自@Bryan的修复,&#39; KnownTypeAttribute&#39;应该在基类上,所以它应该是这样的:
[DataContract(Name="DataFelt")]
[KnownType(typeof(somenamespace.Konstant))]
public class DataFelt
并在子类中:
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
答案 6 :(得分:0)
改变这个:
[DataContract(Name="Konstant")]
public class Konstant : DataFelt
到此:
[DataContract(Name="Konstant")]
[KnownTypes(typeof(somenamespace.DataFelt))]
public class Konstant : DataFelt