Какая сериализация по умолчанию используется ASP.net HttpRuntime.Cache - PullRequest
6 голосов
/ 29 января 2010

Просто интересно, знает ли кто-нибудь окончательно, что такое сериализация по умолчанию, используемая ASP.net HttpRuntime.Cache? Это двоичный файл, XML, что-то еще?

Я спрашиваю, потому что у меня есть ситуация, когда я заполняю общий список несколькими объектами одного и того же пользовательского типа. Пользовательский тип - это POCO, в этом нет ничего особенного. Все его свойства общедоступны с {get; задавать; }, это публично, у него нет наследования, у него нет интерфейсов. На самом деле это гораздо менее сложно, чем многие другие объекты, которые мы кешируем, которые работают без проблем. Я попытался добавить атрибут [Serializable] в пользовательский класс, и он не имеет никакого эффекта.

Я добавляю список в кеш с уникальным ключом. Список был проверен как заполненный до того, как он был вставлен в кеш, объекты в списке также были проверены как заполненные. Но когда список извлекается из кеша, это пустой список (НЕ NULL), в нем просто нет элементов. Это означает, что список добавляется в кеш и доступен для извлечения, но по какой-то причине в кеше возникают проблемы с сериализацией объектов в списке.

Я просто нахожу это странным, потому что у меня есть еще один список пользовательских объектов, которые намного сложнее (состоящий из Наследования, Интерфейсов, а также содержащих Свойства, которые являются общими списками других сложных объектов), и кэширование этих списков работает без вопрос.

Управление рабочим и нерабочим списками осуществляется в классах C # вне пользовательских элементов управления ASP.net, которые используют кэшированные данные. Оба эти класса обработки кэша вызывают один и тот же экземпляр класса Cache Manager, который обертывает HttpRuntime.Cache, чтобы обеспечить типизированные методы для извлечения и переноса объектов в кеш.

У кого-нибудь есть идеи, что может вызвать это. Единственное, что я могу понять - это то, что свойство Blurb объекта Document потенциально может содержать HTML, но если ASP.net использует двоичную сериализацию для кэша, я не понимаю, как это могло бы сработать.

Вот класс

public class Document
{
    public string ContentTypeId { get; set; }
    public string ContentId { get; set; }
    public bool IsCustom { get; set; }
    public Language DocLanguage { get; set; }
    public string RegularTitle { get; set; }
    public string InvertedTitle { get; set; }
    public string Blurb { get; set; }
}  

Вот подкласс, используемый в свойстве Language

public class Language
{
    public string Name { get; set; }
    public string Code { get; set; }
}

Ответы [ 3 ]

5 голосов
/ 29 января 2010

Согласно Reflector, HttpRuntime.Cache вообще не сериализует данные, а просто хранит их в памяти в Hashtable.

Вы говорите, что оборачиваете вызовы в кэш внутри своего единственного объекта-одиночки.Почему ты делаешь это?HttpRuntime.Cache является статическим свойством, поэтому ваши методы-оболочки также могут быть статическими.

0 голосов
/ 04 апреля 2012

Кэши, как правило, не сериализуют и не клонируют объекты, которые вы в них помещаете. Они просто связывают ключ с объектом, который вы передаете. И поскольку списки являются ссылочными типами, любые изменения, внесенные в список, будут видны, когда ключ используется для извлечения из кэша. Поэтому я предполагаю, что вы удаляете элементы из списка после того, как вставляете его. Вот почему клон на вставке разрешил это.

0 голосов
/ 29 января 2010

Немного подробнее о среде, в которой происходит эта кеширующая аномалия.

У меня есть пользовательский элемент управления ASP.net, который представляет контейнер с вкладками на странице. Этот элемент управления содержит список тем, выбранных пользователем. Для каждой темы, выбранной пользователем, этот элемент управления создает новую вкладку для этой темы, содержащую документы, относящиеся к этой теме.

Элемент управления создает новую вкладку, используя метод LoadControl, предоставленный ASP.net. Затем он назначает вновь созданному элементу управления вкладками тему из своего списка. Каждый элемент управления вкладки знает, как найти документы по назначенной теме.

Именно в этом элементе управления вкладкой было реализовано кэширование. Ключ кеша, используемый для кеширования списков документов, полностью уникален для сайта + тема + пол + возраст пользователя, просматривающего тему. Это позволяет спискам документов кэшироваться и извлекаться по всему сайту всеми пользователями, которые соответствуют этим критериям.

Хорошо, когда списки документов были переданы в кеш, они передавались обычными старыми ссылками на объекты (т.е. списки документов = _documents). но когда вытащил из кеша список был пуст.

Хотя каждый элемент управления вкладкой является его собственным экземпляром того же пользовательского элемента управления, и все переменные, используемые в элементе управления вкладками, являются частными для этого элемента управления и должны быть специфичными для этого элемента управления. Я достиг конца своей веревки и, несмотря на то, что отдельные вкладки не могли перезаписывать личные списки друг друга, я решил, что должна быть какая-то безумная ссылочная ошибка, и если это так, то мне нужно прекратить использование ссылочных объектов в кеше и отправлять в кэш только новые копии списков, которые я пытался сохранить.

Затем я использовал следующий метод расширения для List <> и клонировал каждый список по мере его передачи в кэш. Это позволило сделать так, чтобы все элементы, передаваемые в кэш, были совершенно новыми объектами с собственным пространством в памяти и уникальными ссылками на эту память.

ИСПРАВЛЕНО. КЕШИНГ СЕЙЧАС РАБОТАЕТ. Списки теперь возвращаются именно так, как они были добавлены в кеш. Я понятия не имею, почему это будет иметь значение, если у кого-то есть какие-то идеи, я бы хотел их услышать.

    /// <summary>
    /// Clones the specified list to clone.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="listToClone">The list to clone.</param>
    /// <returns></returns>
    public static IList<T> Clone<T>(this IList<T> listToClone) where T : ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...