Strongly-typed access to EPiSever properties using generics and extension methods

When building an EPiServer template, a common task is to retrieve the value of a property before showing it on the page. This property could be of any type and may even be null if the content editor has not supplied a value. On our early EPiSever projects it was typical to find a utility method similar to that below, which would help to avoid NullReferenceExceptions

public string GetProperty(string propertyName)
{
    if (CurrentPage[propertyName] == null)
    {
        return string.Empty;
    }
    return (string)CurrentPage[propertyName];
}

This is useful up to a point, but sprinkle some generics and it then becomes very powerful

public T GetProperty<T>(string propertyName)
{
    if (CurrentPage[propertyName] == null)
    {
        return default(T);
    }
    return (T)CurrentPage[propertyName];
}

Not only does the method now return a strongly-typed value, which saves the developer having to cast, it also copes nicely with missing values. By using the default keyword we are telling .NET to create the default value for the requested type. For instance a missing integer would cause 0 to be returned.

One gotcha to be aware of is that, for missing string properties, null will be returned and not String.Empty as you may expect. This is because string is a reference type, not a value type like int, DateTime and so on. Calling default(T) on reference types will always return a null reference.

Despite this GetProperty is a handy function to have on an EPiServer project and will likely be used tens or even hundreds of times depending on the size of the site being built.

Using extension methods

Ideally this function would form part of the EPiServer PageData class itself, rather than being an isolated helper method. Then we could call it as follows

int someValue = CurrentPage.GetProperty<int>("someProperty");

Although it might seem that inheritance can help us to achieve our aim, that is not the case. OK, we could create a new class which inherits PageData, and add GetProperty to that, but EPiServer would carry on using PageData regardless. What we need to do is add code directly to PageData.

Until version 3 of the .NET framework this would have been impossible to do. However a new feature called extension methods allows us to “spot-weld” methods and properties to any class at all, even System.Object.

Changing GetProperty to an extension method gives us the following

public static class PageDataExtensions
{
    public static T GetProperty<T>(this PageData page, string propertyName)
    {
    if (page[propertyName] == null)
    {
        return default(T);
    }
    return (T)page[propertyName];
    }
}

The method has been moved into a different, static, class. The key difference though, is the addition of a PageData parameter, which has the this keyword applied to it. Doing so tells .NET to extend that class with this method.

To use the extension method, add a using statement to import the new PageDataExtensions class, start typing CurrentPage.Properties.Get and you will see that IntelliSense has detected it. So just call it like any other function, as follows

decimal someValue = CurrentPage.GetProperty<decimal>("someDecimalProperty");

This is a really simple technique to use and is very effective in helping to better organise code. As Nessa from Gavin and Stacey would say, “Tidy!”.

Tags: ,

One Response to “Strongly-typed access to EPiSever properties using generics and extension methods”

  1. Magnus says:

    This is a neat solution. Was just thinking of getting my extension functions generic. So this was a nice push in right direction. =^)

Leave a Reply