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);
}

Так что если:

  1. Ваш пользовательский распознаватель происходит от DefaultContractResolver, и
  2. вы используете один и тот же экземпляр резолвера каждый раз, и
  3. ваши объекты данных имеют одинаковый тип (даже если они имеют разные данные)

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

Другие вопросы по тегам