/// <summary> /// Downloads the specified syndication <paramref name="feeds"/> and merges them into an observable sequence. /// </summary> /// <param name="formatter">The object that reads each feed.</param> /// <param name="client">The object used to make the web request.</param> /// <param name="feeds">The <see cref="Uri"/> objects identifying the feeds to be downloaded.</param> /// <remarks> /// <alert type="tip"> /// To get the original <see cref="SyndicationFeed"/> for each <see cref="SyndicationItem"/>, use the <see cref="SyndicationItem.SourceFeed"/> property. /// </alert> /// </remarks> /// <returns>An observable sequence of items from all of the feeds merged together.</returns> public static IObservable<SyndicationItem> DownloadObservable(this SyndicationFeedFormatter formatter, WebClient client, IEnumerable<Uri> feeds) { Contract.Requires(formatter != null); Contract.Requires(client != null); Contract.Requires(feeds != null); Contract.Ensures(Contract.Result<IObservable<SyndicationItem>>() != null); return (from uri in feeds select Observable.Defer(() => from stream in client.OpenReadObservable(uri) select GetFeed(stream, formatter))) .Concat() .SelectMany(feed => feed.Items.Do(item => { if (item.SourceFeed == null) { item.SourceFeed = feed; } })); }