JsonConvert.SerializeObject - Пользовательский ContracteResolver не вызывает CreateProperty для нескольких вызовов
У меня есть пользовательский ContracteResolver, и я получаю непредсказуемые результаты.
Используя отладчик, я вижу, что при сериализации метод CreateProperty распознавателя вызывается для каждого свойства. Тем не менее, если я делаю 2 вызова подряд, метод CreateProperty не вызывается при втором вызове. Моя точка останова в CreateProperty никогда не попадает на второй проход, она попадает на первый.
Вот моя установка:
IContractResolver contractResolver = new ShouldSerializeContractResolver(fieldsToSerialize, this.Data);
var settings = new JsonSerializerSettings()
{
ContractResolver = contractResolver
};
_payload = JsonConvert.SerializeObject(this.Data, Formatting.None, settings);
Мое исходное значение (this.Data) отличается для обоих вызовов. Результаты (_payload) также отличаются для обоих вызовов. Я не думаю, что что-то кешируется.
Я видел похожий вопрос, вызванный пользовательским ContentNegotiator, но я им не пользуюсь.
Почему бы CreateProperty не попасть на второй проход?
1 ответ
Класс DefaultContractResolver кэширует контракты для каждого типа объекта для лучшей производительности. Вы можете увидеть это в исходном коде, где он создает кеш внутри конструктора:
public DefaultContractResolver()
{
...
_contractCache = new ThreadSafeStore<Type, JsonContract>(CreateContract);
}
А также как это используется, когда договоры разрешаются для каждого типа:
public virtual JsonContract ResolveContract(Type type)
{
ValidationUtils.ArgumentNotNull(type, nameof(type));
return _contractCache.Get(type);
}
Так что если:
- Ваш пользовательский распознаватель происходит от DefaultContractResolver, и
- вы используете один и тот же экземпляр резолвера каждый раз, и
- ваши объекты данных имеют одинаковый тип (даже если они имеют разные данные)
тогда это нормально и ожидается, что CreateProperty
будет вызван только для первой сериализации.