Лучший способ создать полный список объектов только для чтения

Я использую C# 4.0, Asp.Net. У меня возникла проблема с правильным построением структуры readonly в созданном мной пользовательском кеше.

Подробности (краткое описание):
Мой класс CacheManager (синглтон) использует в качестве параметра экземпляр существующего класса MemoryCache и включает в себя несколько полезных методов для работы с дополнительными вещами, такими как жизнь объекта. цикл в моем пользовательском кеше.

Этот менеджер имеет дело с простым CachableObject, который принимает три переменные:

  • object
  • DateTime
  • int (продолжительность)

Таким образом, мой пользовательский менеджер кеша хранит objects в течение ограниченного периода времени, чтобы защитить мою базу данных от частых больших запросов.

В последнее время я пытался:

  • Вернул объект из кеша (то есть: хранится под ключом -MyList)
  • Вернул его обратно в список сложных объектов
  • Переведено содержание некоторых свойств для каждого сложного объекта
  • Снова сохранен только что переведенный список объектов в кеше (под другим ключом -MyTranslatedList)

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

Вопрос:
Как вы можете легко догадаться, я хотел бы защитить себя и других пользователей моего синглтона от подобных ошибок.

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

Что я пробовал до сих пор:
я пытался сделать object доступным только для чтения. Это не сработало, как ожидалось.

Поскольку я часто храню список сложных объектов, я нашел метод AsReadOnly, который возвращает IReadOnlyCollection, но, хотя это не позволяет мне изменять список (добавлять, удалять), он не защищает объекты, находящиеся в списке.

Я надеюсь, что мое объяснение несколько понятно :) Есть ли изящный способ справиться с такой ситуацией?


person Andy M    schedule 12.03.2015    source источник
comment
Нет, невозможно запретить кому-то изменять объект, если у него есть ссылка на него. Если вы действительно не хотите изменять объекты, вы можете сделать их ICloneable или предоставить для них интерфейс только для чтения.   -  person JustSomeGuy    schedule 12.03.2015
comment
Вы можете использовать неизменяемые коллекции   -  person Sameer    schedule 12.03.2015
comment
@Sameer Спасибо за ответ, Самир. Насколько я понял, коллекции Immutable обеспечивают потокобезопасный доступ к списку, который не изменится. Это не гарантирует, что элемент в списке не будет изменен... Вы понимаете, о чем я?   -  person Andy M    schedule 12.03.2015
comment
@Spo1ler Спасибо за ответ, Spo1ler. Мммм, проблема в том, что, поскольку я помещаю случайный объект в свой кеш, я не могу изменить все свои объекты, чтобы сделать их ICloneable. Имеет ли это смысл ?   -  person Andy M    schedule 12.03.2015


Ответы (1)


Я бы создал класс, свойства которого доступны только для чтения:

class ReadonlyClass
{
    private string p1;
    private int p2;

    public ReadonlyClass(string property1, int property2)
    {
        p1 = property1;
        p2 = property2;
    }

    public string Property1
    {
        get { return p1; }
    }

    public int Property2
    {
        get { return p2; }
    }
}

Если свойства являются объектами/другими классами, вы должны реализовать функцию клонирования, которая возвращает копию объекта. Функция клонирования для вышеуказанного класса будет выглядеть так:

    public ReadonlyClass clone()
    {
        return new ReadonlyClass(p1, p2);
    }

С уважением Ханс Миллинг...

person nivs1978    schedule 12.03.2015
comment
Привет Ганс, Спасибо за ваш ответ. Дело в том, что в моем кеше могут быть любые объекты. Сюда также входят объекты, созданные вне моего исходного кода, например объекты Entity Framework, возвращаемые из запросов. - person Andy M; 12.03.2015