Информация о сериализации типов кеша Json.NET?

В .NET-мире, когда дело доходит до сериализации объектов, оно обычно идет на проверку полей и свойств объекта во время выполнения. Использование отражения для этого задания обычно медленное и нежелательно при работе с большими наборами объектов. Другим способом является использование IL emit или построение деревьев выражений, которые обеспечивают значительное увеличение производительности за счет отражения. И последнее – это самые современные библиотеки, которые выбирают при работе с сериализацией. Однако для создания и испускания ИЛ во время выполнения требуется время, и инвестиции выплачиваются только тогда, когда эта информация кэшируется и повторно используется для объектов того же типа.

При использовании Json.NET мне непонятно, какой метод описан выше, и если последний действительно используется, используется ли кеширование.

Например, когда я это делаю:

JsonConvert.SerializeObject(new Foo { value = 1 }); 

Создает ли Json.NET информацию о доступе к члену Foo и кэш для повторного использования позже?

Json.NET кэширует информацию о сериализации типа внутри своих classов IContractResolver DefaultContractResolver и CamelCasePropertyNamesContractResolver . Если вы не укажете пользовательский разрешитель контракта, эта информация будет кэшироваться и повторно использоваться.

Для DefaultContractResolver глобальный статический экземпляр поддерживается внутри, что Json.NET использует, когда приложение не указывает свой собственный решатель контракта. CamelCasePropertyNamesContractResolver другой стороны, CamelCasePropertyNamesContractResolver поддерживает статические таблицы, общие для всех экземпляров. (Я считаю, что несогласованность возникает из-за проблем с наследием, см. Здесь подробности).

Оба эти типа предназначены для обеспечения полной поточности, поэтому совместное использование streamов не должно быть проблемой.

Если вы решите создать свой собственный контрактный преобразователь, тогда информация типа будет кэшироваться и повторно использоваться, если вы будете кэшировать и повторно использовать экземпляр разрешающего конфликта. Таким образом, для «безгосударственных» преобразователей (те, которые не изменяют свои возвращаемые значения на основе сериализуемого текущего экземпляра или других условий выполнения), Newtonsoft рекомендует :

Примеры кэширования распознавателя контрактов в приложении для обеспечения оптимальной производительности.

Одна из страtagsй обеспечения кэширования в подclassе DefaultContractResolver заключается в том, чтобы сделать его конструктор защищенным или приватным и предоставить глобальный статический экземпляр. (Конечно, это подходит только в том случае, если распознаватель всегда должен возвращать одни и те же результаты.) Например, в этом вопросе , вот пример pascal, чтобы подчеркнуть разрешитель контракта:

 public class PascalCaseToUnderscoreContractResolver : DefaultContractResolver { protected PascalCaseToUnderscoreContractResolver() : base() { } // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." static PascalCaseToUnderscoreContractResolver instance; // Using an explicit static constructor enables lazy initialization. static PascalCaseToUnderscoreContractResolver() { instance = new PascalCaseToUnderscoreContractResolver(); } public static PascalCaseToUnderscoreContractResolver Instance { get { return instance; } } static string PascalCaseToUnderscore(string name) { if (name == null || name.Length < 1) return name; var sb = new StringBuilder(name); for (int i = 0; i < sb.Length; i++) { var ch = char.ToLowerInvariant(sb[i]); if (ch != sb[i]) { if (i > 0) // Handle flag delimiters { sb.Insert(i, '_'); i++; } sb[i] = ch; } } return sb.ToString(); } protected override string ResolvePropertyName(string propertyName) { return PascalCaseToUnderscore(propertyName); } } 

Который вы бы использовали как:

 var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings { ContractResolver = PascalCaseToUnderscoreContractResolver.Instance }); 
Давайте будем гением компьютера.