Сводные данные и изолированное хранилище в Silverlight

ОГЛАВЛЕНИЕ

Silverlight — это идеальное решение для создания приложений для чтения сводок новостей. Это решения позволяет читать сводные форматы RSS и AtomPub, сообщается со службами в Интернете при помощи HTTP-запросов, а также обрабатывает междоменные политики. При получении сводных данных их можно считывать в структуру классов, выполнять их синтаксический анализ при помощи LINQ и представлять пользователю в виде связки данных на базе XAML.

В этом разделе приведу описание, как можно использовать эти уникальные функции для создания средства чтения сводных новостей. Таже покажу способы отладки при неполадках, возникающих при сообщении веб-служб Silverlight и как сохранять данные локально при помощи изолированного хранилища. Все используемые примеры доступны в разделе загрузки кода MSDN. 

Завершающий цикл

Метод организации веб-каналов сводных данных позволяет получать доступ к форматам RSS и AtomPub через веб-службы. Каждый веб-канал классифицируется по URI, который возвращает XML, содержащий объекты потока в форматах RSS или AtomPub. На примере приложения, идущего к этой публикации, можно рассмотреть способы чтения сводных данных с применеием запросов веб-службы в адрес приложения Silverlight. Перед тем, как перейти к подробному изложению, мне, возможно, следует показать вам конечную версию приложения. После этого мы рассмотрим логику и различные аспекты кода приложения.

На рис. 1 изображено приложение Silverlight, которое в настоящий момент обрабатывает два сводных веб-канала.

 http://pipes.yahooapis.com/pipes/pipe.run?_id=957­
  d9624940693fb9f9644d7b12fb0e9&_render=rss 
http://pipes.yahooapis.com/pipes/pipe.run?_id=057559bac7aad6640b­
  c17529f3421db0&_render=rss  

 

Рис. 1. Приложение SilverlightSyndication

При нажатии пользователем кнопки «Добавить» отправляется веб-запрос на сбор данных веб-канала. URI веб-канала хранится на компьютере локально, при этом название службы веб-канала отображается в верхней части элемента управления данными типа «сетка».

Хранение URI на клиенте позволяет приложению Silverlight получать данные нужных веб-каналов при запуске приложения. При сборе данных веб-канала объекты размещаются в список, после чего выполняется их синтаксический анализ при помощи LINQ. После этого отсортированные результаты помещаются в нижнюю часть элемента управления «сетка».

Веб-запросы по протоколу HTTP и организация веб-каналов

Использование сводных веб-каналов данных от приложений Silverlight начинается с возможности выполнения веб-запросов. Классы WebClient и HttpWebRequest оба могут создавать веб-запросы протокола HTTP для приложений Silverlight. Первый шаг в этом процессе – принятие решения относительно способа, каким бдут создаваться веб-запросы HTTP. В большинстве случаев достаточно использовать класс WebClient, поскольку он проще в использовании (и тоже обращается к классу HttpWebRequest в скрытой форме). Однако, класс HttpWebRequest позволяет расширенно дорабатывать формулируемые запросы.

На примере этого отрезка кода видно, как можно создать запрос при помощи класса WebClient:

//feedUri is of type Uri 
WebClient request = new WebClient();
request.DownloadStringCompleted += AddFeedCompleted;
request.DownloadStringAsync(feedUri);

С другой стороны, на примере следующего отрезка можно увидеть формирование похожего запроса при помощи класса HttpWebRequest:

//feedUri is of type Uri 
WebRequest request = HttpWebRequest.Create(feedUri);
request.BeginGetResponse(new AsyncCallback(ReadCallback), request);

Класс WebClient более прост в использовании, поскольку в нем используются некоторые возможности класса HttpWebRequest.

Поскольку все веб-запросы протокола HTTP в адрес Silverlight выполняются асинхронно с использованием как класса WebClient, так и класса HttpWebRequest, необходимо понимать, как следует обрабатывать данные, которые будут возвращены после запроса. Когда класс HttpWebRequest заканчивает выполнение серии асинхронных запросов, то не гарантируется, что в потоке интерфейса будет готовый обработчик событий. Если даные извлечены и должны отбражаться в элементе пользовательского интерфейса, то необходимо создать вызов элемента интерфейса так, чтобы управление вновь перешло от фонового потока потоку интерфейса. Это можно сделать при помощи класса Dispatcher или класса SyndicationContext. В следующем примере кода показано, как можно сформулировать запрос потока интерфейса при помощи метода BeginInvoke класса Dispatcher:

Deployment.Current.Dispatcher.BeginInvoke(() =>
{
  MyDataGrid.DataContext = productList;
});

В этом примере кода используется переменная productList (которой присвоено значение, соответствующее данным, возвращенным после отправки запроса веб-службы), которая помещается в контекст DataContext элемента интерфейса. В этом случае сетка данных DataGrid будет связана со списком продуктов. Однако использовать класс Dispatcher не обязательно в том случае, если запрос сделан при помощи класса WebClient. В этом случае код прямо назначит список продуктов контексту данных DataContext элемента интерфейса.

Чтобы использовать класс SynchronizationContext, необходимо создать экземпляр класса SynchronizationContext в том месте, где доступен поток интерфейса. Конструктор или обработчик событий загрузки подходят в качестве такого места. На этом примере кода поясняется инициализация поля _syncContext в конструкторе классов:

public Page() {
_syncContext = SynchronizationContext.Current;

В этом коде видно, как экземпляр SynchronizationContext при помощи метода Post выполняет вызов метода LoadProducts. При этом он обеспечивает доступ к потоку интерфейса метода LoadProducts:

if (_syncContext != null) {
  _syncContext.Post(delegate(object state){ LoadProducts(products); } 
  ,null);

Кроме простоты в использовании, запросы WebClient всегда возвращаются в поток интерфейса. Это означает, что любые результаты запроса класса WebClient можно без затруднений связать с элементами интерфейса без использования Dispatcher (или, вместо него, класса SynchronizationContext). Класс WebClient полностью соответствует требованиям чтения сводных даных. Именно он будет использоваться в приложении, которым сопровождается эта статья.