下午好,
我有一个非常有趣的时间试图说服'yield'关键字以我能理解的方式运作,但不幸的是我运气不好。这是场景:
根据用户的属性,我想查找一组RSS提要地址,并显示来自所有这些提要的七篇最新文章,而不是每个那些饲料。为此,我正在尝试从每个Feed中构建最近五篇文章的集合,然后从这些文章中获取最近的7篇文章。 (非常沉闷的)伪代码类型进程类似于:
我做了一些研究,并且能够产生以下内容:
public static class RSSHelper
{
public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake)
{
foreach (string Feed in feedList)
{
yield return GetLatestArticlesFromFeed(Feed).OrderByDescending(o => o.PublishDate).Take(articlesToTake).First();
}
yield return null;
}
private static IEnumerable<SyndicationItem> GetLatestArticlesFromFeed(string feedURL)
{
// We're only accepting XML based feeds, so create an XML reader:
SyndicationItem Result = new SyndicationItem();
int SkipCount = 0;
for (int Curr = 1; Curr <= 5; Curr++)
{
try
{
XmlReader Reader = XmlReader.Create(feedURL);
SyndicationFeed Feed = SyndicationFeed.Load(Reader);
Reader.Close();
Result = Feed.Items.OrderByDescending(o => o.PublishDate).Skip(SkipCount).Take(1).Single();
SkipCount++;
}
catch (Exception ex)
{
// Do nothing, else the Yield will fail.
}
yield return Result;
}
}
}
似乎正在发生的是我得到五个结果(articlesToTake是7,而不是5),偶尔整个SyndicationItem为null,或者它的属性为null。我也相信这是解决这个问题的一种非常非常糟糕的方法,但在这种情况下我无法找到使用yield关键字的方向。
我确实找到了this question,但它并没有帮助我理解任何事情。
我正在尝试以这种方式实现,或者我只需要咬紧牙关并使用几个foreach循环?
答案 0 :(得分:0)
使用async
和await
将RSS Feed加载到内存中,然后按日期排序,只需Take前7个
答案 1 :(得分:0)
考虑到你想要在GetLatestArticlesFromFeed中做的所有事情是获得5个最新项目,是不是更容易只订购一次列表然后采取前5项?它看起来像这样(与第一种方法的基于SelectMany的方法一起)
public static class RSSHelper
{
public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake)
{
return feedList.SelectMany(f => GetLatestArticlesFromFeed(f)).OrderByDescending(a => a.PublishDate).Take(articlesToTake);
}
private static IEnumerable<SyndicationItem> GetLatestArticlesFromFeed(string feedURL)
{
// We're only accepting XML based feeds, so create an XML reader:
SyndicationFeed feed = null;
try
{
using (XmlReader reader = XmlReader.Create(feedURL))
{
feed = SyndicationFeed.Load(reader);
}
return feed.Items.OrderByDescending(o => o.PublishDate).Take(5);
}
catch
{
return Enumerable.Empty<SyndicationItem>();
}
}
}
如果这不起作用,请告诉我!
答案 2 :(得分:0)
上午,
既然我不觉得死亡变暖了,我已经开始工作了!感谢@Rodrigo和@McKabue寻求最终答案的帮助,感谢@ NPSF3000指出我原来的愚蠢!
结果我已经解决了这个问题:
public static class RSSHelper
{
public static IEnumerable<SyndicationItem> GetLatestArticlesFromFeeds(List<string> feedList, short articlesToTake)
{
return GetLatestArticlesFromFeedsAsync(feedList, articlesToTake).Result;
}
private async static Task<IEnumerable<SyndicationItem>> GetLatestArticlesFromFeedsAsync(List<string> feedList, short articlesToTake)
{
List<Task<IEnumerable<SyndicationItem>>> TaskList = new List<Task<IEnumerable<SyndicationItem>>>();
foreach (string Feed in feedList)
{
// Call and start a task to evaluate the RSS feeds
Task<IEnumerable<SyndicationItem>> T = Task.FromResult(GetLatestArticlesFromFeed(Feed).Result);
TaskList.Add(T);
}
var Results = await Task.WhenAll(TaskList);
// Filter the not null results - on the balance of probabilities, we'll still get more than 7 results.
var ReturnList = Results.SelectMany(s => TaskList.Where(w => w.Result != null).SelectMany(z => z.Result).OrderByDescending(o => o.PublishDate)).Take(articlesToTake);
return ReturnList;
}
private async static Task<IEnumerable<SyndicationItem>> GetLatestArticlesFromFeed(string feedURL)
{
// We're only accepting XML based feeds, so create an XML reader:
try
{
XmlReader Reader = XmlReader.Create(feedURL);
SyndicationFeed Feed = SyndicationFeed.Load(Reader);
Reader.Close();
return Feed.Items.OrderByDescending(o => o.PublishDate).Take(5);
}
catch (Exception ex)
{
return null;
}
}
}
我花了一些时间来绕过头,因为我忘记定义我正在开始的任务的结果类型,但幸好我今天早上偶然发现this question,这有助于一切顺利进入的地方。
我觉得有点厚颜无耻回答我自己的问题,但总的来说,我认为这是一个很好的,整洁的建议答案之间的平衡,它肯定似乎功能。我会添加一些强化和评论,当然,如果有人有反馈,我会感激地收到它。
谢谢! 灰