По поводу хранения настроек приложения написано уже очень много статей. Но о том, что сохранять свои данные можно так же в изолированном хранилище - очень мало упоминаний. Я не буду рассказывать о том, что это такое (об этом очень хорошо написано на MSDN), я просто хочу предложить некоторое решение, которое позволит вам хранить свои данные без особых усилий.
Что из себя представляют настройки приложения? Это коллекция пар ключ/значение. То есть это некоторый IDictionary<TKey, TValue>, где в качестве ключа выступает, как правило, строковый параметр, а в качестве значения, в идеале, может быть любой объект. Если внимательно посмотреть на пространство имен System.IO.IsolatedStorage, то можно обнаружить, что класс с таким функционалом уже есть - это IsolatedStorageSettings. Однако он доступен только для Silverlight и Silverlight for Windows Phone. А для настольных приложений доступен только класс IsolatedStorageFile, который представляет область изолированного хранения, содержащую файлы и папки. То есть разработчики настольных приложений здесь несколько обделены функционалом. Собственно этот пробел я и решил заполнить.
Идея до безобразия проста: ключ - это файл в изолированном хранилище, в котором хранится значение этого ключа в виде сериализованных двоичных данных. Однако, если ключ будет состоять из символов, которые не могут содержаться в имени файла (\/:*?"<>|), возникает проблема. Решение, в принципе, такое же простое - хранить значения оригинальных ключей в отдельном служебном файле и каждому такому значению сопоставлять уникальный идентификатор, по имени которого будет создаваться файл для хранения значения оригинального ключа. Если не совсем понятно, то надеюсь рисунок все прояснит:
На этом теория заканчивается, приступаем к практике. Для начала создадим вспомогательный класс для сохранения объектов в изолированном хранилище в виде двоичных данных:
Также в этом классе есть метод, который проверяет, возможно ли сериализовать объект или нет. Теперь можно реализовать собственный класс IsolatedStorageSettings (который по своему интерфейсу похож на класс, который доступен в Silverlight):
Как вы можете заметить, словарь IDictionary<String, KeyValuePair<Guid, Object>> dictionary хранит оригинальный ключ и пару уникального идентификатора вместе со значением ключа. Данный класс запечатанный и имеет статическое свойство, которое возвращает его экземпляр (это сделано для того, чтобы иметь один экземпляр на все приложение). Стандартные свойства я описывать не буду, а приведу содержание метода Restore(), который восстанавливает ранее сохраненные значения:
Сначала мы получаем ключи и соответствующие им уникальные идентификаторы из служебного файла, затем по идентификаторам восстанавливаем значения ключей из файлов и сохраняем в словарь.
Остается реализовать стандартные операции (CUD) для этого класса. Приведу код на примере создания нового ключа в настройках (весь код можно посмотреть в исходниках на GitHub):
Открытый метод TryAdd() вначале проверяет входные параметры, затем, если ключ с таким значением уже существует - обновляет его, иначе - создает новый. Закрытые методы TryAddWithNotification() и TryUpdateWithNotification() выполняют всю работу по сохранению значений и сообщают об изменении коллекции. Использовать данный класс достаточно удобно:
Данный класс я реализовал как потокобезопасный, таким образом можно сохранять настройки приложения из различных потоков. Есть замечания или есть что добавить? С удовольствием прочитаю ваши комментарии...
Исходный код
Идея до безобразия проста: ключ - это файл в изолированном хранилище, в котором хранится значение этого ключа в виде сериализованных двоичных данных. Однако, если ключ будет состоять из символов, которые не могут содержаться в имени файла (\/:*?"<>|), возникает проблема. Решение, в принципе, такое же простое - хранить значения оригинальных ключей в отдельном служебном файле и каждому такому значению сопоставлять уникальный идентификатор, по имени которого будет создаваться файл для хранения значения оригинального ключа. Если не совсем понятно, то надеюсь рисунок все прояснит:
(info.dat - служебный файл, Key - оригинальный ключ, Guid - уникальный идентификатор)
На этом теория заканчивается, приступаем к практике. Для начала создадим вспомогательный класс для сохранения объектов в изолированном хранилище в виде двоичных данных:
IsolatedStorageSerializer.cs:
Также в этом классе есть метод, который проверяет, возможно ли сериализовать объект или нет. Теперь можно реализовать собственный класс IsolatedStorageSettings (который по своему интерфейсу похож на класс, который доступен в Silverlight):
IsolatedStorageSettings.cs:
Как вы можете заметить, словарь IDictionary<String, KeyValuePair<Guid, Object>> dictionary хранит оригинальный ключ и пару уникального идентификатора вместе со значением ключа. Данный класс запечатанный и имеет статическое свойство, которое возвращает его экземпляр (это сделано для того, чтобы иметь один экземпляр на все приложение). Стандартные свойства я описывать не буду, а приведу содержание метода Restore(), который восстанавливает ранее сохраненные значения:
IsolatedStorageSettings.cs:
Сначала мы получаем ключи и соответствующие им уникальные идентификаторы из служебного файла, затем по идентификаторам восстанавливаем значения ключей из файлов и сохраняем в словарь.
Остается реализовать стандартные операции (CUD) для этого класса. Приведу код на примере создания нового ключа в настройках (весь код можно посмотреть в исходниках на GitHub):
IsolatedStorageSettings.cs:
Открытый метод TryAdd() вначале проверяет входные параметры, затем, если ключ с таким значением уже существует - обновляет его, иначе - создает новый. Закрытые методы TryAddWithNotification() и TryUpdateWithNotification() выполняют всю работу по сохранению значений и сообщают об изменении коллекции. Использовать данный класс достаточно удобно:
Program.cs:
Данный класс я реализовал как потокобезопасный, таким образом можно сохранять настройки приложения из различных потоков. Есть замечания или есть что добавить? С удовольствием прочитаю ваши комментарии...
Исходный код
Комментариев нет:
Отправить комментарий