Not A Subscriber?
Join thousands of people who build and refuse to get left behind. One message a week on building, using AI as an accelerator, and staying sharp in the new AI frontier.
Receive one free message a weekFebruary 10, 2009 Donn Felker
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
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.