Сводные данные и изолированное хранилище в Silverlight
ОГЛАВЛЕНИЕ
В этом разделе приведу описание, как можно использовать эти уникальные функции для создания средства чтения сводных новостей. Таже покажу способы отладки при неполадках, возникающих при сообщении веб-служб 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 полностью соответствует требованиям чтения сводных даных. Именно он будет использоваться в приложении, которым сопровождается эта статья.