DataContractJsonSerializer抛出SerializationException,抱怨意外类型,即使我已使用KnownTypeAttribute指定它

时间:2014-09-27 03:16:48

标签: c# .net windows-runtime windows-phone-8.1

说我有以下课程:

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

行[{1}}会抛出serializer.WriteObject(stream, entry);,表示不期望类型SerializationException,我应该使用User来指定它。但我做了(间接)!

我该如何使这项工作?我无法将KnownTypeAttribute移到KnownType类,因为它需要是通用的。为什么不能Entry<T>看到DataContractJsonSerializerExtendedDataList指定为已知类型?

1 个答案:

答案 0 :(得分:0)

我找到了一种让它工作的方法,但仍然无法解释为什么DataContractJsonSerializer忽略了我已应用于KnownType的{​​{1}}属性< / em>的

ExtendedDataList似乎不够聪明,无法注意到我在DataContractJsonSerializer类中指定的KnownType属性;显然它只尊重我附加到ExtendedDataList类的已知类型,因为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); } } 的{​​{1}}属性,然后将这些类型传递给序列化KnownType的任何数据协定序列化程序。

注意:需要TEntry<T>