2014-09-27 49 views
0
指定它

说我有以下类:DataContractJsonSerializer抛出SerializationException,抱怨意想不到的类型,即使我已经与KnownTypeAttribute

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

我申请KnownTypeAttributeExtendedDataList因为那类扩展的基类的一般键入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作为已知类型?

回答

0

我想出了一个办法来得到它的工作,但它仍然没有解释为什么DataContractJsonSerializer是忽略了KnownType属性我申请了ExtendedDataList

看起来DataContractJsonSerializer不够智能,无法注意到我在ExtendedDataList类中指定的KnownType属性;显然这只是荣誉,因为typeof(Entry<T>),我已经连接到Entry<T>类已知的类型,是我给我想要Entry<T>保持一般的DataContractJsonSerializer

的构造,我不希望所有的垃圾它的类型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

相关问题