gpt4 book ai didi

c# - 使用 Newtonsoft JSON 的 ObjectCreationHandling 的说明?

转载 作者:IT王子 更新时间:2023-10-29 04:39:29 26 4
gpt4 key购买 nike

我正在追踪一个错误,我注意到 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 0 Reuse existing objects, create new objects when needed.
Reuse 1 Only reuse existing objects.
Replace 2 Always create new objects.

默认为自动 ( Line 44 )。

Auto 只有在确定当前类型是否有一个 TypeInitializer 为 null 的一系列检查后才会被覆盖。那时它检查是否有无参数构造函数。

///
/// Create a factory function that can be used to create instances of a JsonConverter described by the
/// argument type.
/// The returned function can then be used to either invoke the converter's default ctor, or any
/// parameterized constructors by way of an object array.
///

本质上它的行为是这样的(它看起来像是 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 实例的实例化 List,以及使用 serialized 字符串实例化的新 List .

testObj.List: ABC,DEF,Goodbye,AOL

收藏

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

testObj.Collection: ABC,DEF

只读集合

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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com