Not a subscriber?

Join thousands of others who are building self-directed lives through creativity, grit, and digital strategy—breaking free from the 9–5.
Receive one free message a week

Using Expressions and Func as a Reflection Tool

I’m using Castle Active Record for a project that I’m on and I constantly find myself having to provide column names when creating queries through the ActiveRecordMediator<T> object. Here’s an example:

 

ActiveRecordMediator<Customer>.FindOne(Expression.Eq("FirstName", "Bob")); 

The column name “FirstName” is not strongly typed. If I change that name (or anyone else does) and they don’t use a tool like ReSharper they might run into some issues.

 

So I poked around a bit and found a few examples of what I was trying to do and created my own strongly typed version with this class:

 

/// <summary>
/// Returns the name of a property via an expression. 
/// </summary>
/// <typeparam name="TypeToParsePropertiesFrom">The type to parse properties from.</typeparam>
public interface IPropertyNameResolver<TypeToParsePropertiesFrom>
{
    /// <summary>
    /// Parses a property from the given type. 
    /// </summary>
    /// <typeparam name="PropertyToParse">The property to parse.</typeparam>
    /// <param name="property">The property.</param>
    /// <returns>The property name.</returns>
    string ResolvePropertyName<PropertyToParse>(Expression<Func<TypeToParsePropertiesFrom, PropertyToParse>> property);
}

/// <summary>
/// Class responsible for parsing a property name. 
/// </summary>
/// <typeparam name="TypeToParsePropertiesFrom">The type to parse properties from.</typeparam>
public class PropertyNameResolver<TypeToParsePropertiesFrom> : IPropertyNameResolver<TypeToParsePropertiesFrom>
{
    public string ResolvePropertyName<PropertyToParse>(Expression<Func<TypeToParsePropertiesFrom, PropertyToParse>> property)
    {
        //
        // If the expression body was x.FirstName, it would return a string "x.FirstName". 
        //
        var fullPropertyName = property.Body.ToString();

        //
        // Parse the index of the period and get the propertyName after that. 
        // therefore x.FirstName would return "FirstName"
        //
        return fullPropertyName.Substring(fullPropertyName.IndexOf(".") + 1);
    }
}

 

Usage:

To get a property name using this expression you will need to use a Lambda. Check it out:

IPropertyNameResolver<Customer> customerResolver =
    new PropertyNameResolver<Customer>();

var propertyName = customerResolver.ResolvePropertyName(x => x.FirstName);
Assert.That(propertyName, Is.EqualTo("FirstName"));

The only real con is that I have to create an instance of that generic class to do this. But … the good thing is that its strongly typed.