JsonConvert.SerializeObject - Пользовательский ContracteResolver не вызывает CreateProperty для нескольких вызовов - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть пользовательский 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 Ответ

0 голосов
/ 21 сентября 2018

Класс 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 будет вызываться только для первой сериализации.

...