简体   繁体   English

ICollection <T> 为什么在HashSet上调用SerializationBinder <T> 但不在清单上 <T>

[英]ICollection<T> Why SerializationBinder is call on HashSet<T> but not on List<T>

I have an object like this : 我有一个这样的对象:

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

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

In WebApi i had a SerializationBinder, in my webApiConfig : 在WebApi中,我的webApiConfig中有一个SerializationBinder:

jsonFormatter.SerializerSettings.Binder = new DefaultSerializationBinder();

When I call my controller that return my all object i get a structure like this 当我调用返回我所有对象的控制器时,我得到了这样的结构

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

But if i change my constructor with an hashset 但是如果我用哈希集更改构造函数

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

The result of my controller is like this : 我的控制器的结果是这样的:

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

I would like understand why ? 我想知道为什么吗? What is the difference which induce this behavior ? 导致这种行为的区别是什么?

Is-it possible to use a HashSet but give the same result like with the list ? 是否可以使用HashSet,但给出与列表相同的结果?

EDIT : 编辑:

@Grundy comment : @Grundy评论:

TypeNameHandling property is Auto and from doc: Include the .NET type name when the type of the object being serialized is not the same as its declared type. TypeNameHandling属性是Auto,来自doc:当要序列化的对象的类型与其声明的类型不同时,请包括.NET类型名称。 So seems HashSet serialized is not the same as its declared type. 因此,似乎HashSet序列化与其声明的类型不同。

It's true, it's the reason, but why it's not true for List ? 是的,这是事实,但是对于List来说,事实并非如此? The type is different of ICollection like HashSet... ICollection的类型与HashSet等不同。

Moreover, I try to change TypeNameHandling property but there no option for set $type only on inherited objects... 此外,我尝试更改TypeNameHandling属性,但是没有设置set type仅在继承对象上的选项。

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

Thanks to @Grundy for the clue. 感谢@Grundy提供的线索。

I keep 我一直

jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;

and I had a custom JsonConverter to change the serialization of HashSet 我有一个自定义的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);
    }
}

and add it in config : 并将其添加到config中:

jsonFormatter.SerializerSettings.Converters.Add(new HashSetArrayConverter());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM