ObjectCreationHandling

ObjectCreationHandling

我正在跟踪一个错误,我注意到Newtonsoft JSON会将项目追加到已在默认构造函数中初始化的List<>中。我做了一些进一步的挖掘,并在C#聊天中与一些人进行了讨论,我们注意到这种行为并不适用于所有其他集合类型。

https://dotnetfiddle.net/ikNyiT

using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections.ObjectModel;

public class TestClass
{
    public Collection<string> Collection = new Collection<string>(new [] { "ABC", "DEF" });
    public List<string> List = new List<string>(new [] { "ABC", "DEF" });
    public ReadOnlyCollection<string> ReadOnlyCollection = new ReadOnlyCollection<string>(new [] { "ABC", "DEF" });
}

public class Program
{
    public static void Main()
    {
        var serialized = @"{
            Collection: [ 'Goodbye', 'AOL' ],
            List: [ 'Goodbye', 'AOL' ],
            ReadOnlyCollection: [ 'Goodbye', 'AOL' ]
        }";


        var testObj = JsonConvert.DeserializeObject<TestClass>(serialized);

        Console.WriteLine("testObj.Collection: " + string.Join(",", testObj.Collection));
        Console.WriteLine("testObj.List: " + string.Join(",", testObj.List));
        Console.WriteLine("testObj.ReadOnlyCollection: " + string.Join(",", testObj.ReadOnlyCollection));
    }
}

输出:
testObj.Collection: ABC,DEF
testObj.List: ABC,DEF,Goodbye,AOL
testObj.ReadOnlyCollection: Goodbye,AOL

如您所见,Collection<>属性不受反序列化的影响,List<>附加到了ReadOnlyCollection<>上。这是预期的行为吗?这是什么原因?

最佳答案

基本上可以归结为类型实例化和 ObjectCreationHandling 设置。 ObjectCreationHandling共有三种设置



默认值为auto(Line 44)。

仅在一系列确定当前类型的TypeInitializer是否为null的检查之后,Auto才会被覆盖。此时,它将检查是否存在无参数构造函数。



本质上,它的行为是这样的(看起来像是6类中的1500行代码)。

ObjectCreationHandling och = ObjectCreationHandling.Auto;
if( typeInitializer == null )
{
 if( parameterlessConstructor )
 {
  och = ObjectCreationHandling.Reuse;
 }
 else
 {
  och = ObjectCreationHandling.Replace;
 }
}

此设置是JsonSerializerSettings的一部分,它是在DeserializeObject的访客模式构造器内部组成的。如上所示,每个设置都有不同的功能。

回到List,Collection和ReadOnlyCollection,我们将研究每个条件语句的集合。

列表
testObj.List.GetType().TypeInitializer == null为假。结果,List接收默认的ObjectCreationHandling.Auto,并在反序列化期间使用testObj实例的实例化列表,并使用serialized字符串实例化新的List。
testObj.List: ABC,DEF,Goodbye,AOL

收藏
testObj.Collection.GetType().TypeInitializer == null为true表示没有可用的反射类型初始化器,因此我们转到下一个条件,即检查是否有无参数构造函数。 testObj.Collection.GetType().GetConstructor(Type.EmptyTypes) == null为假。结果,Collection收到ObjectCreationHandling.Reuse的值(仅重用现有对象)。从testObj使用了Collection的实例化实例,但是serialized字符串无法实例化。
testObj.Collection: ABC,DEF

ReadOnlyCollection
testObj.ReadOnlyCollection.GetType().TypeInitializer == null为true表示没有可用的反射类型初始化器,因此我们转到下一个条件,即检查是否有无参数构造函数。 testObj.ReadOnlyCollection.GetType().GetConstructor(Type.EmptyTypes) == null也是如此。结果,ReadOnlyCollection接收到ObjectCreationHandling.Replace的值(始终创建新对象)。仅使用serialized字符串中的实例化值。
testObj.ReadOnlyCollection: Goodbye,AOL

关于c# - 使用Newtonsoft JSON进行ObjectCreationHandling的解释?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27848547/

10-11 05:57