Provider Pattern for Consuming Feeds

So I started working on a new project where we’re taking the Service-First-Design approach (post on that coming soon!) and it basically consumes feeds such as RSS, Atom and other types of feeds right in the service layer. Since we wanted to allow for any number of feed formats we decided to implement the provider pattern instead of a big ol’ switch or if-else statement. Below are some snippets and pseudo code on how that worked out for us…

IFeedProvider.cs

[[code lang=”csharp[lines]”]]czo2NTpcInB1YmxpYyBpbnRlcmZhY2UgSUZlZWRQcm92aWRlcg0Kew0KICAgdm9pZCBQcm9jZXNzKEZlZWQgZmVlZCk7DQp9XCI7e1smKiZdfQ==[[/code]]

The IFeedProvider interface gives us a nice simple standard interface to start working with. All we added for now is a “Process” method that each class implementing this interface will use to process the feeds.

RssFeedProvider.cs

[[code lang=”csharp[lines]”]]czo2Mzk6XCJwdWJsaWMgY2xhc3MgUnNzRmVlZFByb3ZpZGVyIDogSUZlZWRQcm92aWRlcg0Kew0KICAgcHVibGljIHZvaWQgUHJvY2V7WyYqJl19c3MoRW50aXRpZXMuRmVlZCBmZWVkKQ0KICAgew0KICAgICAgdmFyIHJzcyA9IFJzc0ZlZWQuQ3JlYXRlKG5ldyBVcmkoZmVlZC5VcntbJiomXX1sKSk7DQogICAgICBpZiAocnNzICE9IG51bGwpDQogICAgICB7DQogICAgICAgICBmb3JlYWNoICh2YXIgcnNzSXRlbSBpbiByc3Mue1smKiZdfUNoYW5uZWwuSXRlbXMuV2hlcmUoaSA9PiBpLlB1YmxpY2F0aW9uRGF0ZSA+IGZlZWQuRGF0ZUxhc3RVcGRhdGVkKSkNCiAgICAgICB7WyYqJl19ICB7DQogICAgICAgICAgICBmZWVkLkZlZWRJdGVtcy5BZGQobmV3IEZlZWRJdGVtDQogICAgICAgICAgICB7DQogICAgICAgICAgIHtbJiomXX0gICAgVGl0bGUgPSByc3NJdGVtLlRpdGxlLA0KICAgICAgICAgICAgICAgVXJsID0gcnNzSXRlbS5MaW5rLlRvU3RyaW5nKCksDQoge1smKiZdfSAgICAgICAgICAgICAgRGF0ZUNyZWF0ZWQgPSBEYXRlVGltZS5VdGNOb3csDQogICAgICAgICAgICB9KTsNCiAgICAgICAgIH0NCiB7WyYqJl19ICAgICAgICAvLyB1cGRhdGUgRGF0ZUxhc3RVcGRhdGVkIG9uIGVhY2ggZmVlZA0KICAgICAgICAgZmVlZC5EYXRlTGFzdFVwZGF0ZXtbJiomXX1kID0gRGF0ZVRpbWUuVXRjTm93Ow0KICAgICAgfQ0KICAgfQ0KfVwiO3tbJiomXX0=[[/code]]

The RssFeedProvider implements IFeedProvider interface and the Process method. The Process method simply takes in a Feed entity from our Entity Framework data model and processes it accordingly. In case you’re wondering we are using Argotic on CodePlex to parse out the RSS, Atom and OPML feeds. Works like a charm! Now back to the provider pattern…

AtomFeedProvider.cs

[[code lang=”csharp[lines]”]]czoxNTA6XCJwdWJsaWMgY2xhc3MgQXRvbUZlZWRQcm92aWRlciA6IElGZWVkUHJvdmlkZXINCnsNCiAgIHB1YmxpYyB2b2lkIFByb2N7WyYqJl19ZXNzKEVudGl0aWVzLkZlZWQgZmVlZCkNCiAgIHsNCiAgICAgIC8vVE9ETzogSGFuZGxlIHlvdXIgQXRvbSBmZWVkcyBoZXJlDQogIHtbJiomXX0gfQ0KfVwiO3tbJiomXX0=[[/code]]

This AtomFeedProvider class also implements IFeedProvider (logic stripped for brevity).

FeedHandler.cs

[[code lang=”csharp[lines]”]]czo0NDg6XCJwdWJsaWMgY2xhc3MgRmVlZEhhbmRsZXINCnsNCiAgIHZhciBjb250ZXh0ID0gbmV3IE15RGF0YUNvbnRleHQoKTsNCiB7WyYqJl19ICB2YXIgZmVlZHMgPSBjb250ZXh0LkZlZWRzLlRvTGlzdCgpOzwvZmVlZD4NCiAgIElGZWVkUHJvdmlkZXIgZmVlZFByb3ZpZGVyIHtbJiomXX09IG51bGw7DQogICBmb3JlYWNoICh2YXIgZmVlZCBpbiBmZWVkcykNCiAgIHsNCiAgICAgIGZlZWRQcm92aWRlciA9DQogICAgICAge1smKiZdfSAgKElGZWVkUHJvdmlkZXIpQWN0aXZhdG9yLkNyZWF0ZUluc3RhbmNlKFwiWW91ckxpYnJhcnlcIiwNCiAgICAgICAgIFN0cmluZy5Db3tbJiomXX1uY2F0KFwiWW91ckxpYnJhcnkuTmFtZXNwYWNlLlwiLCBmZWVkLkNsYXNzTmFtZSkpLlVud3JhcCgpOw0KICAgICAgZmVlZFByb3ZpZGV7WyYqJl19ci5Qcm9jZXNzKGZlZWQpOw0KICAgfQ0KICAgY29udGV4dC5TYXZlQ2hhbmdlcygpOw0KICAgY29udGV4dC5EaXNwb3NlKCk7DQp9XCJ7WyYqJl19O3tbJiomXX0=[[/code]]

Once you have your interface done and at least two (for testing purposes) providers ready to go, you can create your class that will call the providers. In this example, using Entity Framework, we simply pull a list of RSS and Atom feeds that are stored in a SQL database. For each feed we are going to call Activator.CreateInstance and pass in the library and namespace of the provider. Don’t forget to call the UnWrap() method at the end to unwrap the instance into your variable declared with the interface type, in this case, “IFeedProvider”.

Finally, once you have your variable containing the instance of your feed provider, you can call the “Process” method implemented in each of the providers. Once you have processed all the feeds, call SaveChanges on your context and commit the feed items to the database. You can also implement caching and return the feed items back out through the service layer as JSON or an aggregated RSS feed which is what we are doing in our project. Sky’s the limit!

Enjoy.

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInShare on Reddit