我正在跟踪一个错误,我注意到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/