Windows RSS Platform Preview
曾经翻译过Longhorn中的RSS,那是Microsoft正式在Longhorn中加入RSS支持的白皮书。大概2个星期前吧,看到了Microsoft RSS Team Blog上面提到的Screen Saver的例子,才发现随着IE7 Beta2的发布,已经可以看到这个RSS Platform了。
大概看了一下整个文档,然后用C#编了个简单的小程序试了试,还不错,API还算合理好用,这下Desktop平台的对RSS支持变得非常容易了。
Windows RSS Platform的Online Reference在这里。
- Subscribe to new feeds, and enumerate existing subscriptions.
- Easily access properties of feeds (channels), feed items, and enclosures.
- Manage and organize feeds into folders.
- Listen for and respond to feed and feed folder events.
- Check the status of the background Feed Download Engine, or modify settings.
- Normalize the Extensible Markup Language (XML) source of a feed.
这是Windows RSS Platform的对象体系图:

整个类体系的Top Class是FeedsManager,顺便说一句,XXManager一般都是各种类体系结构中的Top Class,是整个API的入口。比如Eclipse平台的Platform,比如Adapter体系的AdapterManager,比如Plugin体系中的PluginManager。
具体细节就不多说了,举几个简单的例子:(为了简单,我用C#试的,C++访问的话,就是访问COM接口,也很简单)
1) 同步RSS
- Feeds.IFeedsManager fs = new Feeds.FeedsManagerClass();
- fs.BackgroundSync(Feeds.FEEDS_BACKGROUNDSYNC_ACTION.FBSA_RUNNOW);
2) 订阅Feed Event
- Feeds.IFeedFolderEvents_Event e = (Feeds.IFeedFolderEvents_Event)folder.GetWatcher(Feeds.FEEDS_EVENTS_SCOPE.FES_ALL, Feeds.FEEDS_EVENTS_MASK.FEM_FEEDEVENTS);
- e.FeedAdded += new Feeds.IFeedFolderEvents_FeedAddedEventHandler(FeedAdded);
- private static void FeedAdded(string path) {
- System.Diagnostics.Debug.Print(path);
- }
显然,Delegate的典型用法,如果用C++,当然就是使用IConnectionPoint来把回调函数加入到Feeds COM Object中的Notifier List。
3) 得到系统当前Feed列表(包括Feed Item Count)
- foreach (Feeds.IFeed feed in CommonFeedListUtils.CommonFeedList(folder))
- {
- System.Diagnostics.Debug.Print("Found feed {0} with {1} items.",feed.name, ((Feeds.IFeedsEnum)feed.Items).Count);
- try
- {
- }
- catch (System.Runtime.InteropServices.COMException ex)
- {
- System.Diagnostics.Debug.Print("Failed to get RSS feed '{0}' from API; skipping feed. Error: {1} ", feed.name, ex.ToString());
- // Ignore exception, meaning ignore this feed and continue with next feed.
- }
- }
- public static IEnumerable CommonFeedList(IFeedFolder folder) {
- Queue queue = new Queue();
- queue.Enqueue(folder);
- while (queue.Count > 0) {
- IFeedFolder currentFolder = queue.Dequeue();
- foreach (IFeedFolder subfolder in (IFeedsEnum)currentFolder.Subfolders)
- queue.Enqueue(subfolder);
- foreach (IFeed feed in (IFeedsEnum)currentFolder.Feeds) {
- System.Windows.Forms.Application.DoEvents();
- yield return feed;
- }
- }
- }
这段代码是从Screen Saver的例子中拿来的,惭愧的是,看了这段代码,我才知道C#中也有yield :(。再顺便插一句,特意查了一下C# Language Specification,yield是C# 2.0中新增的Feature,C#给出的yield的推荐实现(应该也是Microsoft的实现)是由编译器生成一个enumerator类,一个State Machine,正是这个State实现了yield。
4) 新增Feed或者Feed Folder
- folder.CreateFeed("Xerdoc Together", "http://feeds.feedburner.com/xerdoc");
- folder.CreateSubfolder("Elites");
基本上就是这样,Feed的管理将变的非常简单。不知道这个Platform对离线阅读器会有什么影响,不可否认的是,它很大程度降低了RSS开发的门槛,也使你可以更加将精力专注到逻辑和功能上。
Update:回答Winters的问题
其实看看CSharp2.0 Specification就明白了,其实很简单。它给出的例子是:
- using System;
- using System.Collections;
- using System.Collections.Generic;
- class Stack<T>: IEnumerable<T>
- {
- T[] items;
- int count;
- public void Push(T item) {
- if (items == null) {
- items = new T[4];
- }
- else if (items.Length == count) {
- T[] newItems = new T[count * 2];
- Array.Copy(items, 0, newItems, 0, count);
- items = newItems;
- }
- items[count++] = item;
- }
- public T Pop() {
- T result = items[--count];
- items[count] = default(T);
- return result;
- }
- public IEnumerator<T> GetEnumerator() {
- for (int i = count - 1; i >= 0; --i) yield return items[i];
- }
- }
编译的时候生成一个enumerator辅助类:
- class Stack<T>: IEnumerable<T>
- {
- ...
- public IEnumerator<T> GetEnumerator() {
- return new __Enumerator1(this);
- }
- class __Enumerator1: IEnumerator<T>, IEnumerator
- {
- int __state;
- T __current;
- Stack<T> __this;
- int i;
- public __Enumerator1(Stack<T> __this) {
- this.__this = __this;
- }
- public T Current {
- get { return __current; }
- }
- object IEnumerator.Current {
- get { return __current; }
- }
- public bool MoveNext() {
- switch (__state) {
- case 1: goto __state1;
- case 2: goto __state2;
- }
- i = __this.count - 1;
- __loop:
- if (i < 0) goto __state2;
- __current = __this.items[i];
- __state = 1;
- return true;
- __state1:
- --i;
- goto __loop;
- __state2:
- __state = 2;
- return false;
- }
- public void Dispose() {
- __state = 2;
- }
- void IEnumerator.Reset() {
- throw new NotSupportedException();
- }
- }
- }
In the preceding translation, the code in the iterator block is turned into a state machine and placed in the MoveNext method of the enumerator class. Furthermore, the local variable i is turned into a field in the enumerator object so it can continue to exist across invocations of MoveNext.
Popularity: 66%
Related entries:
- No Related Posts

April 10th, 2006 at 1:06 pm
没太看明白这个yield,还有state machine实现yield的机制
有时间的话,能不能详细介绍一下,呵呵
April 10th, 2006 at 9:52 pm
我Update在上面了,呵呵。
June 12th, 2006 at 12:29 pm
最近要搞一个在linux上的RSS Reader,现在还不知如何下手,不知是用java好呢还是用c++还是用php
能给点意见吗 并且能讲讲用c++怎样实现上边的功能
谢谢啦