2015-08-19 89 views
0

我有一個這樣的對象:ICollection的<T>爲什麼SerializationBinder是通話的HashSet <T>但不能在列表<T>

public class MyCollec 
{ 
    public ICollection<MyObject> MyCollection { get; set; } 

    public MyCollec() 
    { 
     MyCollection = new List<MyObject>(); 
    } 
} 

在的WebAPI我有一個SerializationBinder,在我webApiConfig:

jsonFormatter.SerializerSettings.Binder = new DefaultSerializationBinder(); 

當我打電話給我的控制器,返回我的所有對象,我得到了這樣的結構

{ 
    "MyCollection": [ 
    { 
     ... 
    }, 
    { 
     ... 
    } 
    ] 
} 

但是,如果我改變我的構造與HashSet的

public MyCollec() 
{ 
    MyCollection = new HashSet<MyObject>(); 
} 

我的控制器的結果是這樣的:

{ 
    "MyCollection": { 
    "$type": "System.Collections.Generic.HashSet`1[[WebApplication1.Models.MyObject, WebApplication1]], System.Core", 
    "$values": [ 
      { 
       ... 
      }, 
      { 
       ... 
      } 
     ] 
    } 
} 

我想知道爲什麼?引起這種行爲的區別是什麼?

是否有可能使用HashSet,但給與列表相同的結果?

編輯:

@Grundy評論:

TypeNameHandling屬性是汽車,從DOC:包括.NET類型 名當對象被序列化的類型是不一樣的 其聲明類型。所以看起來HashSet序列化和 聲明的類型不一樣。

確實,這是原因,但爲什麼它不適用於List?該類型是一樣的HashSet的ICollection的不同...

而且,我試圖改變TypeNameHandling財產,但有沒有選項僅在繼承的對象集$類型...

http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm

+1

我認爲'默認值TypeNameHandling'屬性是'Auto',來自[doc](http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm):_當被序列化的對象的類型與其聲明的類型不同時,請包括.NET類型名稱。因此,似乎HashSet序列化與其聲明的類型不同。 :-) – Grundy

+0

爲什麼你刪除自己的答案?它真的解決了問題 – Grundy

+0

謝謝,我相信解決我的問題,但不是。因爲如果我將TypeNameHandling設置爲TypeNameHandling.Objects,則會在所有對象上添加$ type,我希望$ type只添加在我的繼承對象上。 – binard

回答

0

感謝@格蘭迪的線索。

我一直

jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; 

,我有一個自定義JsonConverter改變HashSet的

public class HashSetArrayConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     IEnumerable collectionObj = (IEnumerable)value; 

     writer.WriteStartObject(); 

     foreach (object currObj in collectionObj) 
     { 
      serializer.Serialize(writer, currObj); 
     } 

     writer.WriteEndObject(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     return serializer.Deserialize(reader, objectType); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     var canConvert = IsAssignableToGenericType(objectType, typeof(HashSet<>)); 
     return canConvert; 
    } 

    private static bool IsAssignableToGenericType(Type givenType, Type genericType) 
    { 
     var interfaceTypes = givenType.GetInterfaces(); 

     if (interfaceTypes.Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == genericType)) 
     { 
      return true; 
     } 

     if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) 
      return true; 

     Type baseType = givenType.BaseType; 
     if (baseType == null) return false; 

     return IsAssignableToGenericType(baseType, genericType); 
    } 
} 

的系列化和配置添加:

jsonFormatter.SerializerSettings.Converters.Add(new HashSetArrayConverter()); 
相關問題