Как я могу сделать свойство ObservableCollection только для чтения?

У меня было выполнение успеха, что Вы описываете, но потому что сторонний DLL является также блоком.NET, я никогда не выписываю его к диску, я просто загружаю его из памяти.

я получаю встроенную сборку ресурсов как массив байтов как так:

        Assembly resAssembly = Assembly.LoadFile(assemblyPathName);

        byte[] assemblyData;
        using (Stream stream = resAssembly.GetManifestResourceStream(resourceName))
        {
            assemblyData = ReadBytesFromStream(stream);
            stream.Close();
        }

Тогда я загружаю данные блоком. Загрузка ().

Наконец, я добавляю обработчик к AppDomain. CurrentDomain. AssemblyResolve для возврата моего загруженного блока, когда загрузчик типа смотрит он.

Посмотрите Семинар Fusion.NET для дополнительных деталей.

36
задан Eric J. 18 July 2012 в 21:54
поделиться

4 ответа

Принятый [ранее] ответ фактически будет возвращать разные ReadOnlyObservableCollection при каждом обращении к ReadOnlyFoo. Это расточительно и может привести к тонким ошибкам.

Предпочтительным решением является следующее:

public class Source
{
    Source()
    {
        m_collection = new ObservableCollection<int>();
        m_collectionReadOnly = new ReadOnlyObservableCollection<int>(m_collection);
    }

    public ReadOnlyObservableCollection<int> Items
    {
        get { return m_collectionReadOnly; }
    }

    readonly ObservableCollection<int> m_collection;
    readonly ReadOnlyObservableCollection<int> m_collectionReadOnly;
}

Полное обсуждение см. в Антипаттерн ReadOnlyObservableCollection.

61
ответ дан 27 November 2019 в 05:49
поделиться

Используйте ReadOnlyObservableCollection

public ReadOnlyObservableCollection<T> ReadOnlyFoo
{
    get { return new ReadOnlyObservableCollection<T> (_CollectionOfFoo); }
}

Как уже указывалось, используйте ответ Эрика Дж., Поскольку он по ошибке каждый раз возвращает новый экземпляр.

-1
ответ дан 27 November 2019 в 05:49
поделиться
  • Просто сохраните каждый результат запроса в базе данных (с ключом кеша: ваш запрос, значение: ваш список бизнес-объектов)
  • Используйте распределенный кеш, такой как memcached, рядом с кешем ASP.Net
  • Используйте сложный диспетчер кеша, например https://github.com/enyim/memcached-providers ; которые могут иметь кеш-группы. Некоторые данные должны храниться долго, некоторые - непродолжительное время. Некоторые данные должны храниться в кэше ASP.Net и т. Д.
  • Выполнять вызовы, которые должны храниться в кеше, с помощью функции-оболочки, например public T GetFromCache (строковый ключ, Func ifKeyNotFoundDelegate ) , чтобы кэш всегда использовался одинаково. [1]
  • Подумайте, когда использовать кеш ASP.Net, а когда - распределенный. Данные, которые читаются при каждом запросе, должны храниться в ASP.Net, большие данные, такие как результаты поиска; с множеством разных ключей, данных и т. д. должен быть в memcached.
  • Добавить управление версиями. Приставьте ко всем ключам номер версии, чтобы у вас не было проблем при обновлении веб-приложения, а некоторые объектные контракты изменились.

Ну что ж, это охватывает большую часть того, что мы делаем на нашем веб-сайте (кластер memcached на 20 ГБ, распределенный на 20 серверах

[1] Сделав такую ​​функцию единственным интерфейсом для хранения данных в кэше, вы можете добиться следующего. Допустим, я хочу использовать что-то из кеша, например, результат функции. Обычно вы делаете что-то вроде

CacheManager cm = new CacheManager(CacheGroups.Totals);
object obj = cm.GetFromCache("function1result");
if(obj == null)
{
    obj = (object)DAO.Foo();
    cm.StoreInCache("function1result", obj);
}
return (List<MyEntity>)obj;

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

Like

public T GetFromCache<T>(string key, Func<T> ifnotfound)
{
    T obj = this.GetFromCache(key) as T;
    if(obj == default(T)) 
    { 
         obj = ifnotfound.Invoke();
         this.StoreInCache(key, obj);
    }
    return obj;
}

Это гарантирует, что

  1. Мы всегда работаем с правильным типом
  2. Ваш пользователь всегда работает с кешем одинаково

Следовательно: менее вероятно, что он сделает ошибку. Более того: вы получите более красивый и понятный код, например:

-1
ответ дан 27 November 2019 в 05:49
поделиться

Вы можете изменить тип своего свойства на IEnumerable:

public IEnumerable<foo> CollectionOfFoo { 
     get { 
         return _CollectionOfFoo;
     }
}

Я не верю, что существует стандартный интерфейс, предоставляющий индексатор. Если вам это нужно, вы можете написать интерфейс и расширить ObservableCollection для его реализации:

public interface IIndexerCollection<T> : IEnumerable<T>
{
    T this[int i]
    {
        get;
    }
}

public class IndexCollection<T> : ObservableCollection<T>, IIndexerCollection<T>
{
}
0
ответ дан 27 November 2019 в 05:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: