DataContractJsonSerializer抛出SerializationException,尽管I';我
本文关键字:尽管 抛出 SerializationException DataContractJsonSerializer | 更新日期: 2023-09-27 18:24:55
假设我有以下类:
[DataContract]
class Entry<T>
{
[DataMember]
public T Data { get; set; }
}
[DataContract]
class DataList<T>
{
[DataMember]
public IList<T> Collection { get; set; }
}
[DataContract]
[KnownType(typeof(User))]
class ExtendedDataList : DataList<object>
{
[DataMember]
public string SomeExtraParameter { get; set; }
}
[DataContract]
class User
{
[DataMember]
public string Name { get; set; }
}
我已经将KnownTypeAttribute
应用于ExtendedDataList
,因为该类扩展了一般类型object
的基类,并且它将在列表中存储不同类型的对象。在本例中,我标记了一个已知类型的User
,因为我知道它将包含User
对象。
这是序列化代码:
var user = new User { Name = "Bob" };
var users = new ExtendedDataList { Collection = new List<object> { user } };
serialize(users);
带有
static void serialize<T>(T obj)
{
var entry = new Entry<T>();
entry.Data = obj;
var stream = new MemoryStream();
var serializer = new DataContractJsonSerializer(typeof(Entry<T>));
serializer.WriteObject(stream, entry);
stream.Seek(0, SeekOrigin.Begin);
var r = new StreamReader(stream);
var s = r.ReadToEnd();
System.Diagnostics.Debug.WriteLine(s);
}
行serializer.WriteObject(stream, entry);
抛出一个SerializationException
,说类型User
不是预期的,我应该使用KnownTypeAttribute
来指定它。但我(间接地)做到了!
我怎样才能做到这一点?我不能将KnownType
移动到Entry<T>
类,因为它需要是通用的。为什么DataContractJsonSerializer
看不到ExtendedDataList
将User
指定为已知类型?
我找到了让它工作的方法,但它仍然不能解释为什么DataContractJsonSerializer
忽略了我应用于ExtendedDataList
的KnownType
属性。
DataContractJsonSerializer
似乎不够聪明,没有注意到我在ExtendedDataList
类上指定的KnownType
属性;显然,它只接受我附加到Entry<T>
类的已知类型,因为typeof(Entry<T>)
是我赋予DataContractJsonSerializer
构造函数的类型
我希望Entry<T>
保持通用性,不想让它包含各种KnownType
属性。因此,我使用以下类定义:
[DataContract]
[KnownType("KnownTypes")]
class Entry<T>
{
[DataMember]
public T Data { get; set; }
public static IEnumerable<Type> KnownTypes()
{
var attrs = typeof(T).GetTypeInfo().GetCustomAttributes<KnownTypeAttribute>();
return attrs.Select(attr => attr.Type);
}
}
这使用反射来获取附加到内部类型T
的KnownType
属性,然后将这些类型传递给序列化Entry<T>
的任何数据协定序列化程序。
注:需要using System.Linq
和using System.Reflection
。