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看不到ExtendedDataListUser指定为已知类型?

DataContractJsonSerializer抛出SerializationException,尽管I';我

我找到了让它工作的方法,但它仍然不能解释为什么DataContractJsonSerializer忽略了我应用于ExtendedDataListKnownType属性

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

这使用反射来获取附加到内部类型TKnownType属性,然后将这些类型传递给序列化Entry<T>的任何数据协定序列化程序。

注:需要using System.Linqusing System.Reflection