-
-
Notifications
You must be signed in to change notification settings - Fork 17
[MediaWiki] Generators
IAsyncEnumerable<T> and IAsyncEnumerator<T> are introduced in Ix.Async package as asynchronous counterpart for IEnumerable<T> and IEnumerator<T>. With Ix.Async package, You can consume these asynchronous enumerators in a somewhat similar manner as you are working with ordinary enumerators.
- You can use all the LINQ extension methods on
IAsyncEnumerator<T>. - You can use
Rx.NETpackage to convertIAsyncEnumerator<T>toIObservable<T>, if necessary. - For now, you can consume the items in
IAsyncEnumerator<T>sequentially using the expanded for-each pattern. (SeeShowAllTemplatesAsyncmethod below for example); later whenasync foris introduced into C# 8 (hopefully), you might be able to useasync for eachonIAsyncEnumerator<T>.
Some caveats when consuming the IAsyncEnumerator<T> taken out from generator classes in Wiki Client Library:
- Query continuations are carried out automatically by WCL. You just need to keep enumerating. WCL will request for more results from server when necessary.
- Choose a proper
PaginationSize. It decides (at most) how many items are to be fetched from server in one MediaWiki API request. So for example, if you are working with top 50 items fromRecentChangesGenerator, you might choose 50 asPaginationSizevalue, so they will all be fetched at once.
static async Task SearchAsync()
{
Console.Write("Enter your search keyword: ");
var generator = new SearchGenerator(myWikiSite, Console.ReadLine())
{
PaginationSize = 22
};
// We are only interested in the top 20 items.
foreach (var item in await generator.EnumItemsAsync().Take(20).ToList())
{
Console.WriteLine(item);
Console.WriteLine("\t{0}", item.Snippet);
}
}Most of the WikiPageGenerator-derived classes (including AllPagesGenerator) implement IWikiListGenerator<WikiPageStub>, i.e., .EnumItemsAsync() will return a sequence of WikiPageStub. If you are only interested in the titles of the pages, consider using .EnumItemsAsync() instead of .EnumPagesAsync().
Still, there are some classes implementing IWikiList<T> where T is something other than WikiPageStub, including
class RecentChangesGenerator : WikiPageGenerator<RecentChangeItem, WikiPage>, IWikiList<RecentChangeItem>, IWikiPageGenerator<WikiPage>class RecentChangesGenerator : WikiPageGenerator<RecentChangeItem, WikiPage>, IWikiList<RecentChangeItem>, IWikiPageGenerator<WikiPage>class SearchGenerator : WikiPageGenerator<SearchResultItem, WikiPage>, IWikiList<SearchResultItem>, IWikiPageGenerator<WikiPage>class GeoSearchGenerator : WikiPageGenerator<GeoSearchResultItem, WikiPage>, IWikiList<GeoSearchResultItem>, IWikiPageGenerator<WikiPage>-
class RevisionsGenerator : WikiPagePropertyGenerator<Revision, WikiPage>, IWikiList<Revision>, IWikiPageGenerator<WikiPage>The items These
static async Task ShowAllTemplatesAsync()
{
var generator = new AllPagesGenerator(myWikiSite)
{
StartTitle = "A",
NamespaceId = BuiltInNamespaces.Template,
PaginationSize = 50
};
// You can specify EnumPagesAsync(PageQueryOptions.FetchContent),
// if you are interested in the content of each page
using (var enumerator = generator.EnumPagesAsync().GetEnumerator())
{
int index = 0;
// Before the advent of "async for" (might be introduced in C# 8),
// to handle the items in sequence one by one, we need to use
// the expanded for-each pattern.
while (await enumerator.MoveNext(CancellationToken.None))
{
var page = enumerator.Current;
Console.WriteLine("{0}: {1}", index, page);
index++;
// Prompt user to continue listing, every 50 pages.
if (index % 50 == 0)
{
Console.WriteLine("Esc to exit, any other key for next page.");
if(Console.ReadKey().Key == ConsoleKey.Escape)
break;
}
}
}
}