Программирование HTTP с использованием WCF - Создание SyndicationFeed

ОГЛАВЛЕНИЕ

Создание SyndicationFeed

Существует два способа создания объекта SyndicationFeed. Можно создать один экземпляр и заполнить его члены вручную, либо заполнить весь SyndicationFeed из существующего канала. Оба способа просты в исполнении и скрывают от разработчика особенности реализации конкретного формата подключения. В следующем коде показан способ создания вручную объекта SyndicationFeed.

SyndicationFeed feed = new SyndicationFeed();
feed.Title.Text = "The Cybertopian Chronicle";

Заголовок является всего лишь одним из многих свойств, которые можно устанавливать, поэтому дополнительные возможности следует искать в документации.

Зачастую возникает необходимость считать информацию из существующего канала и выполнить какие-то операции на основе содержимого этого канала. В новом интерфейсе API объединения предусмотрено создание SyndicationFeed и автоматическое заполнение его состояния из существующего канала. Все, что требуется для запуска, это URI-адрес существующего канала или XmlReader, предназначенный для его чтения. В следующем коде показан способ подключения к существующему каналу в Интернете и извлечение из него некоторой информации:

Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);
Console.WriteLine(feed.Title.Text);

// outputs "The Cybertopian Chronicle"

В тип SyndicationItem входит более 35 членов. Многие из них являются свойствами, связанными с установкой или извлечением полей, таких как идентификатор элемента, дата последнего обновления, заголовок или фактическое содержимое. Существуют многочисленные члены, облегчающие расширение содержимого, хранящегося в SyndicationItem. Имеется много расширений RSS и ATOM (Microsoft Simple List Extensions, Yahoo Media RSS и GeoRSS, помимо многих других), и как SyndicationFeed, так и SyndicationItem допускает расширение с целью включения любого существующего расширения RSS или ATOM.

В каналах может быть много элементов, и одновременная их загрузка является негодным вариантом в случае больших каналов. SyndicationFeed справляется с этой ситуацией, предоставляя объект SyndicationItem в качестве IEnumerable<SyndicationItem>. Эта реализация облегчает работу с большим числом объектов SyndicationItem, поскольку в ней используется преимущество применения итератора среды .NET Framework 2.0. Итерации на наборе объектов SyndicationItem можно также выполнять с помощью LINQ. Это может значительно сократить объем кода, требуемого для извлечения данных из канала.

Объединенный интерфейс API определяет несколько типов, преобразующих SyndicationFeed в форматы RSS 2.0 и ATOM 1.0. Фактически, можно создать один SyndicationFeed, заполнить его объектами SyndicationItem, затем предоставить этот канал одновременно как RSS и ATOM. На рис. 5 показано, как получить канал ATOM 1.0, преобразовать его в RSS 2.0 и вывести новое представление RSS на консоль.

Рис. 5 Transforming a Feed

// read an ATOM feed
Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);

// transform it to RSS
Rss20FeedFormatter formatter = new Rss20FeedFormatter(feed);
XmlWriter writer = XmlWriter.Create(Console.Out, null);

// write it to the Console
formatter.WriteTo(writer);
writer.Flush();

Сочетая объединенный интерфейс API с моделью программирования HTTP в среде WCF, можно предоставить канал от настроенного URI-адреса и вернуть RSS или ATOM, основанные на компоновке этого URI-адреса. На рис. 6 показано, как определить операцию в контракте службы, которая параметр строки запроса от принятого HTTP GET использует для возврата либо канала RSS, либо канала ATOM. Обратите внимание на использование SyndicationFeedFormatter<SyndicationFeed> в контракте операции. Как Rss20FeedFormatter, так и Atom10FeedFormatter являются производными от SyndicationFeedFormatter<TSyndicationFeed>.

Рис. 6 Exposing a Feed from a Customized URI

[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
[ServiceContract]
interface IPictureService {
  [OperationContract]
  [WebGet(UriTemplate="Pictures?format={format}")]
  SyndicationFeedFormatter<SyndicationFeed> Feed(String format);
}

class PictureService : IPictureService {

  public SyndicationFeedFormatter<SyndicationFeed> Feed(String format){
  // create the syndication feed 
  SyndicationFeed feed = new SyndicationFeed();

  // add the items to the feed (omitted)

  // check the argument & return the right format
  if(format.ToLower() == "rss"){
  return new Rss20FeedFormatter(feed);
  }
  return new Atom10FeedFormatter(feed);
  }
}