A few days ago, I came up with an interesting concept to enable quick and easy parsing and generation of syndication content feeds. Rather than using the standard approach of using an XML document and using XPath to parse a feed into some other structure, I set about experimenting with Reflection to translate a feed into a corresponding .NET class structure.

After a while, I started writing my own serialization framework, but this is strictly targeted at quick and dirty implementations of feed reading and writing.

To summarize in brief terms, all you need to do is create a corresponding class for whatever feed type you want to consume - for simplicity's sake, we will consider the XSPF playlist format, but you could apply the same principles to RSS and ATOM.

Using a set of base classes I have implemented, I can read and write valid XSPF using just three classes, these classes define the primary objects of an XSPF file.

The playlist:

public class Playlist : ChannelBase, IChannel
{
    public string title { get; set; }
    [OptionalElement()]
    public string creator { get; set; }
    [OptionalElement()]
    public string annotation { get; set; }
    [OptionalElement()]
    public string info { get; set; }
    [OptionalElement()]
    public string location { get; set; }
    [OptionalElement()]
    public string identifier { get; set; }
    [OptionalElement()]
    public string image { get; set; }
    [OptionalElement()]
    public DateTime date { get; set; }
    [OptionalElement()]
    public string license { get; set; }
    
    [ComplexElement()]
    public TrackCollection trackList { get; set; }
}

The track:

public class Track : Syndication.Core.IComplexElement
{
    public string location { get; set; }
    public string title { get; set; }
    [OptionalElement()]
    public string identifier { get; set; }
    [OptionalElement()]
    public string creator { get; set; }
    [OptionalElement()]
    public string annotation { get; set; }
    [OptionalElement()]
    public string info { get; set; }
    [OptionalElement()]
    public string image { get; set; }
    [OptionalElement()]
    public string album { get; set; }
    [OptionalElement()]
    public Int32 trackNum { get; set; }
    [OptionalElement()]
    public Int32 duration { get; set; }
}

And lastly a Collection of Tracks called trackList.

We only need to implement classes for custom structures that are stored in a feed. This is normally anything that is not a standard .NET DataType such as in the case above - a Track. These custom structures have to implement a custom Interface called IComplexElement which contains one routine to parse the corresponding XmlNode for that class.

Now here comes the fun bit..

Using a combination of Reflection, the structures discussed above, and XmlDocument, I can parse an entire XSPF file in 24 lines of code and place the results into a corresponding .NET class - strong typing rules OK! - The built-in functions in .NET for deriving type name and formatting values combined with some key custom attributes to specify optional or complex properties help a lot here as it enables the parsing routine to determine how to set the property value correctly and/or parse child values where required. Here you can see the parse routine at work. And because ComplexElements (custom classes) must implement their own Parse routine, these classes are created, and their relevant parse routine is called, passing the current XML child node as a parameter.

public override void Parse(XmlDocument xml)
{
    this.trackList.Clear();
    XmlNode root = xml.GetElementsByTagName("playlist")[0];
    if (root == null) { return; }
    foreach (XmlNode node in root.ChildNodes)
    {
        if (ReflectionUtility.IsComplexElement(this, node.Name))
        {
            ReflectionUtility.SetComplexPropertyValue(this, node.Name, node);
        }
        else
        {
            if (ReflectionUtility.IsArray(this, node.Name))
            {
                ReflectionUtility.SetPropertyValue(this, node.Name, node.ChildNodes);
            }
            else
            {
                ReflectionUtility.SetPropertyValue(this, node.Name, node.InnerText);
            }
        }
    }
}

Using this extensible framework, I have so far been able to add support for reading and writing ATOM, RSS, and XSPF feeds and would imagine the framework is sufficiently expandable to allow parsing of other formats when required.

At some stage, a more formal article will appear on CodeProject along with the full source code when I have fully implemented the project..

Peace y'all..

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"