Friday, February 5, 2010

Extender Methods in C#

Extender Methods were added to the .Net Framework in version 3.0 and allow developers to add additional methods to the current base types.  This is done by using static methods and adding a directive with the extender class type.

A simple example

You’ve probably seen this in many times in the code where we find the Name of the user from the current Windows security principle.

string[] strDomainAndUsername = Thread.CurrentPrincipal.Identity.Name.Split('\\');
Employee employee = employeeSearch.VerifyAccess(strDomainAndUsername[1]);

Although this works, its not very readable; what extender methods allow is the ability to add new methods to the base .Net types in this case “string”.

image

Normally hitting “.” at the end of the Name attribute will bring up all the methods that relate to whatever that returning type is, in this case a “string”, so you get .Split(), .Contains(), etc.  But with an Extender Method we can add additional ones, for example “.Username()” and “.Domain()” as shown below;

image

You know its an Extender Method by the icon next to the name.

Implementation

To do this you need to create a new class which is a static and a method within that class that is also static and returns the same type of object.

namespace EnterpriseIreland.Common.Extensions
{

    //Extension methods must be defined in a static class
    public static class StringExtender
    {
        /// <summary>
        /// Usernames the specified identity.
        /// </summary>
        /// <param name="identity">The identity.</param>
        /// <returns></returns>
        public static string Username(this string identity)
        {
            string[] networkidentity = identity.Split('\\');
            if(networkidentity.Length >1)
                return networkidentity[1];
            return "Unknown";
        }

        /// <summary>
        /// Domain Name specified by the identity.
        /// </summary>
        /// <param name="identity">The identity.</param>
        /// <returns></returns>
        public static string Domain(this string identity)
        {
            string[] networkidentity = identity.Split('\\');
            if(!String.IsNullOrEmpty(networkidentity[0]))
                return networkidentity[0];
            return "Unknown";
        }
    }
}

 

Now when you want to use it in your own code all you need to do is add the namespace and it should appear for every string.

using EnterpriseIreland.Common.Extensions;

Employee employee = employeeSearch.VerifyAccess(Thread.CurrentPrincipal.Identity.Name.Username());

Which is far more readable.  Although this is a fairly trivial example you can do fairly complex code functions using this method.  Imagine something like this for Project information put out in a HTML grid format by Year or perhaps generic Currency conversion?

     string projectsToHTMLGrid =  project.FindAllByProperty(“Year”, 2010).ToCSSHTMLOutput();

     double US  =  project.TotalIncentive.ConvertCurreny(“US”);

I’ve set out a standard in the Wiki for doing this type of thing in your projects, feel free to try it out if you see the need.