-->

dev dotnet, rss

When you listen to a podcast, your podcast player downloads the RSS feed of the publisher. Then, it checks the locally downloaded files and downloads the new ones as they come along. In this small project, I will develop a small C# application that downloads the entire media from an RSS feed.

All the information in the RSS feed is public, and all RSS clients download these media files.

Here’s how the program works in a nutshell:

  • It accepts two arguments: the URL of the RSS feed and the target directory to save the files into
  • It then downloads the RSS feed into a temporary XML file
  • It parses the XML and gets the following values: Title, publication date and the URL to download
  • It loops through all the entries in the feed and saves the files to the local file system (It skips existing files so you can run it multiple times, and it won’t re-download unnecessarily)
  • Finally, it deletes the temp XML file

That’s all! Not a fancy podcatcher; it’s a fun little project you can use to archive your favourite podcasts.

The entire source code for the C# Console Application is below. Enjoy!

using System.Xml;
using System.Net;

string feedUrl = args[0];
string feedLocalFileNnme = "temp-feed.xml";

string targetLocalDirectory = args[1].TrimEnd('/');

using (var client = new WebClient())
{
    Console.WriteLine($"Downloading {feedUrl} to {feedLocalFileNnme}");
    client.DownloadFile(feedUrl, feedLocalFileNnme);
}

string rawXml = File.ReadAllText(feedLocalFileNnme);
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(rawXml);

XmlNodeList itemNodeList = xmlDocument.SelectNodes("/rss/channel/item");

for (int i = 0; i < itemNodeList.Count; i++)
{
    XmlNode titleNode = itemNodeList[i].SelectNodes("title")[0];
    XmlNode enclosureNode = itemNodeList[i].SelectNodes("enclosure")[0];
    XmlNode pubDateNode = itemNodeList[i].SelectNodes("pubDate")[0];
    string urlToDownload = enclosureNode.Attributes["url"].Value;
    DateTime pubDate = DateTime.Parse(pubDateNode.InnerText);
    string localFileName = $"{targetLocalDirectory}/{GetDate(pubDate)}-{titleNode.InnerText}.mp3";
    if (!File.Exists(localFileName))
    {
        using (var client = new WebClient())
        {
            Console.WriteLine($"Downloading {urlToDownload} to {localFileName}");
            client.DownloadFile(urlToDownload, localFileName);
            Thread.Sleep(2000);
        }
    }
    else
    {
        Console.WriteLine($"Skipping. File at {localFileName} already exists.");
    }
    
    string GetDate(DateTime pubDate)
    {
        return $"{pubDate.Year}-{pubDate.Month.ToString().PadLeft(2, '0')}-{pubDate.Day.ToString().PadLeft(2, '0')}";
    }
}

File.Delete(feedLocalFileNnme);

Usage

dotnet run -- {RSS URL} {Target Local Directory}

Resources

dev dotnet

In the previous post, we discussed using the var keyword. One of the primary use cases of the var keyword is anonymous types. In this post, we are going to look closer into anonymous types.

Anonymous types

An anonymous type is a nameless class that inherits from an object.

The type is inferred, by the compiler, at initialization.

For example, a typical anonymous declaration would look like this:

var person = new 
{
  FirstName = "John",
  LastName = "Power",
  Age = 33
};

We can see, just like any other object, it supports IntelliSense. We can see all the properties we defined and the methods coming from the Object class, such as ToString() and Equals(). So it is a strongly-typed class. We don’t know the type.

Auto-complete showing the properties of person object

The properties are read-only. If we try to assign another value, we get the following error:

Compilation error (line 11, col 3): Property or indexer 'AnonymousType#1.Age' cannot be assigned to -- it is read only

IDE showing error when assigning value to property

Since we don’t have a handle on the class, how can we create another object of this type? The answer is simple: We make another anonymous type with the same properties.

For example, the following example would compile successfully:

public class Program
{
    public static void Main()
    {
        var firstPerson = new 
        {
          FirstName = "John",
          LastName = "Power",
          Age = 33
        };

        var secondPerson = new 
        {
          FirstName = "Jane",
          LastName = "Power",
          Age = 44
        };

        firstPerson = secondPerson;
    }
}

secondPerson can be assigned to firstPerson as they have the same type. An assignment is only possible if all the properties match. If we remove the Age property from the secondPerson, we get the error shown below:

Compilation error (line 18, col 17): Cannot implicitly convert type 'AnonymousType#1' to 'AnonymousType#2'

Shorthand Declarations

We don’t need to specify the property names if we assign the object from another. So, for example, if we wanted to create a second object of the same type with the same values, we could use this syntax:

Auto-complete showing the properties on secondPerson object

As shown in the screenshot above, we can still see the same property names as the firstPerson object.

The same feature exists in ES6.

Internals of Anonymous Types

So what happens when we compile our application with anonymous types? The type names are generated automatically by the compiler.

The example below shows what our class looks like with an IL viewer:

The output of IL viewer showing the compiler output of anonymous types

We declared the firstPerson and secondPerson objects defined (of the same type) as:

instance void class '<>f__AnonymousType0`3'<string, string, int32>::.ctor(!0/*string*/, !1/*string*/, !2/*int32*/)

These auto-generated type names are hidden from the developer because we don’t need to know what they are. So it’s generally a bad practice to find out these types via reflection.

The final example shows the IL output when I’ve removed the Age property from the secondPerson object. Now that the properties don’t match with firstPerson, the compiler generates a new type for secondPerson named <> f__AnonymousType1’2:

The output of IL viewer showing the compiler output of anonymous types when Age property is removed from secondPerson object

Resources

dev dotnet, csharp

The var keyword in C# gives the programmer freedom to declare variables with implicit types. However, when to use it is a highly debated subject in the C# community. This post will look at the origins of the var keyword and our conclusion on when to use it.

Origins

Microsoft introduced the var keyword in C# 3.0, which allows declaring “implicit” variable declarations. However, the variables declared with the var keyword are still strongly typed. The difference is that you don’t need to declare it yourself; the compiler determines the type.

For example, the following code would not compile:

var i = 10;
i = "x";

When i is declared, the type is determined to be an integer, so the string assignment fails with the following error:

Compilation error (line 7, col 7): Cannot implicitly convert type 'string' to 'int'

For the same reason, as you can imagine, you cannot just declare a variable with var type such as:

var i;

which would fail with the following error:

Implicitly-typed local variables must be initialized

Usage

Var keyword mainly has two usages:

  1. Declare anonymous types
  2. Not repeat type name in a variable declaration and object instantiation

The first usage is non-debatable, meaning that var is your only option if you declare anonymous types. Below is an example of using the var keyword to declare an anonymous type:

var person = new {Id = 1, Name = "Jack", Age = 25 }

Another use case is a query expression where you select a new type.

var somePeople = from person in people
                 where person.Age > 20
                 select new { person.Id, person.Name }

In the second example, we create a new type on the fly rather than returning an existing one, so we must use the var keyword.

The debate

The debate around when to use var revolves around the second usage, as the first one is mandatory if you need anonymous types. So, should we use it as a shortcut and skip type declarations? Does that make the code easier or harder to read?

For example, consider a complex variable declaration as shown below:

Dictionary<string, Dictionary<string, List<string>>> items = new Dictionary<string, Dictionary<string, List<string>>>();

We can declare the same variable with the var keyword:

var items = new Dictionary<string, Dictionary<string, List<string>>>();

In my opinion, the second option is a lot clearer and makes the code easier to read.

Try to avoid duplication whenever possible.

Now let’s take a look at another example:

var userService = new UserService();
var user = userService.GetUser(1);

What is the type of “user”? Without the help of the IDE we are using, there is no way to know for sure just by looking at the code above. It can be a User class, an IUser interface, or a subclass of User. At this point, we don’t know.

Conclusion

Here’s my rule of thumb on when to use var:

If the type of the variable is apparent in the initialization of the variable, it’s ok to use the var keyword.

For example, to review the above example, I’d go with explicit usage:

var userService = new UserService();
User user = userService.GetUser(1);

But if I were declaring the variable with a new keyword, I’d go with var:

var user = new User();

The benefit of this approach is especially obvious with complex types like the dictionary shown above:

var items = new Dictionary<string, Dictionary<string, List<string>>>();

In this case, duplicating the type name doesn’t add more clarity.

I hope this article helps you decide when to use the var keyword in C#.

Resources