Fluent null checking

When you want to access nested properties on an object, e.g. Person.Address.Postcode, it’s annoying and bloated having to write this as a series of variable assignments and null checks at each stage if the properties are nullable. The set of extensions below allows the following example:

public string GetSomething(A myClass) {
    var property1 = myClass.Property1;

    if (property1 == null) {
        return string.Empty;
    }

    var property2 = property1.Property2;

    if (property2 == null) {
        return string.Empty;
    }

    return property2.Property3 ?? string.Empty;
}

to be cleanly re-written as…

public string GetSomething(A myClass) {
    return myClass.With(x => x.Property1).With(x => x.Property2).Return(x => x.Property3, string.Empty);
}

using these extensions:

using System;

namespace Extensions
{
    public static class MaybeMonadExtensions
    {
        public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
            where TResult : class
            where TInput : class
        {
            return o == null ? null : evaluator(o);
        }

        public static TResult Return<TInput, TResult>(
            this TInput o,
            Func<TInput, TResult> evaluator,
            TResult failureValue)
            where TInput : class
        {
            return o == null ? failureValue : evaluator(o);
        }

        public static TInput If<TInput>(this TInput o, Func<TInput, bool> evaluator)
            where TInput : class
        {
            if (o == null)
            {
                return null;
            }

            return evaluator(o) ? o : null;
        }

        public static TInput Unless<TInput>(this TInput o, Func<TInput, bool> evaluator)
            where TInput : class
        {
            if (o == null)
            {
                return null;
            }

            return evaluator(o) ? null : o;
        }

        public static TInput Do<TInput>(this TInput o, Action<TInput> action)
            where TInput : class
        {
            if (o == null)
            {
                return null;
            }

            action(o);
            return o;
        }
    }
}

See http://www.codeproject.com/KB/cs/maybemonads.aspx for more details.

Extension to calculate age

using System;

namespace Extensions
{
    public static class DateTimeExtensions
    {
        public static int Age(this DateTime birthDate)
        {
            return Age(birthDate, DateTime.Today);
        }

        public static int Age(this DateTime birthDateTime, DateTime atDateTime)
        {
            var birthDate = birthDateTime.Date;
            var atDate = atDateTime.Date;
            var age = atDate.Year - birthDate.Year;

            if (birthDate.AddYears(age) > atDate)
            {
                age--;
            }

            return age;
        }
    }
}

Accessing clipboard from a C# console application

Simple, but a few non-obvious things required:

1. Add a reference to System.Windows.Forms
2. Add a [STAThread] attribute above the Main method (see here for more information)
3. Now you’re ready to use the methods on Clipboard to write to the clipboard:

...
using System.Windows.Forms;

namespace MyNamespace
{
    public class Program
    {
        [STAThread]
        public static void Main(string[] args)
        {
            Clipboard.SetText("Text to put on the clipboard");
        }
    }
}

Using ELMAH with MVC 3

Whereas ELMAH used to work pretty much straight out of the box, with MVC 3, a change to the global.asax.cs template means that ELMAH won’t automatically catch all errors, since MVC 3 has some built in error handling when custom errors are enabled. To remove this and let ELMAH catch everything, make sure you’ve removed the following line from your global.asax.cs file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute()); // remove at least this line
}

(Note: if you read this wondering what ELMAH is, go here to catch up)