2014-09-27 50 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

相關問題