This post could’ve also been called “Fluent NHibernate secrets exposed!” but it sounded a bit sensationalist.

You may have heard people mention static reflection recently, quite possibly because it’s used extensively in Fluent NHibernate, Rhino Mocks, and I believe Jimmy Bogard’s new AutoMapper also uses it; pretty much any of the new “fluent” interfaces use some kind of static reflection.

So what actually is static reflection? Well, it’s a statically compiled way of utilising the Reflection API.

Traditionally, if you wanted to use the Reflection API to interrogate your classes, you’d need to utilise strings to refer to properties and methods; this can make your design quite brittle, because you have to make sure these strings are kept up-to-date whenever you rename anything. What’s worse is that because reflection is late-bound, you aren’t aware of the problems until the code is actually executed, so this renaming could introduce hidden bugs that don’t appear until runtime. With the growing popularity of refactoring techniques, it’s becoming more important that we can use reflection without having to worry about this problem.

It’s very true that tools like Resharper can certainly help with refactoring reflection-based code, but none of them are perfect and they only help the people that use them.

In C# 3 we were introduced to lambda expressions and Linq, and with them came the Func<> and Expression<> classes; these are the key to static reflection. The Func<> set of classes allow you to use lambda expressions that return a value, while an Expression<> can be used to programatically access the contents of a delegate.

Combining Func<> and Expression<> can give us a very powerful way to statically retrieve PropertyInfo (and similar) instances from a lambda expression. For example Expression<Func<Customer, object>> represents an expression that contains a delegate that returns a value (of type object), with a Customer parameter; I’ll illustrate:

// method to receive an expression
public PropertyInfo GetProperty<TEntity>(Expression<Func<TEntity, object>> expression)

// usage
GetProperty<Customer>(customer => customer.Name);

What this is actually doing is creating a lambda that returns a value, the value of customer.Name in this case. Here’s the trick, we don’t actually care about the value that’s returned! In-fact, we don’t even evaluate this expression at all.

The reason we use object in the Func signature, rather than a more specific type, is because we want to allow any property to be used; however, if you were only interested in string properties, then you could restrict it by replacing this parameter.

The Expression API itself is very in-depth, so I won’t go into the intricacies of it but here’s a very simple implementation of static reflection.

public PropertyInfo GetProperty<TEntity>(Expression<Func<TEntity, object>> expression)
{
  var memberExpression = expression.Body as MemberExpression;

  if (memberExpression == null)
    throw new InvalidOperationException("Not a member access.");

  return memberExpression.Member as PropertyInfo; // Should account for FieldInfo too
}

Stepping through this code, we start by getting the body of the expression which we cast to a MemberExpression; this is us grabbing the customer.Name part of our expression. Now we can get the member itself and cast it to a PropertyInfo, this is the Name part of the expression body. That’s it! We’ve not evaluated the expression, but we’ve inspected it and retrieved the property.

This example is for illustrative purposes, there are many different types of expressions which would be excluded by this. If you are to implement your own static reflection parser, you should cater for these other types of expressions.

As this example shows, we’re able to use reflection without having to resort to strings. The great thing about this is that if you change the name of a member inside a lambda, you’ll get a compile error if you haven’t updated all the references! No more hidden bugs.

So that’s how the magic behind Fluent NHibernate (and others) works, simple when you know how!

Tags:

Comments...

  1. Thank you for explaining this.

    “we don’t actually care about the value that’s returned! In-fact, we don’t even evaluate this expression at all.”

    Please explain more :) Makes the head swim a bit.

    By Steve1 Jan, 2009 @ 1:28 am

  2. Traditionally, when you receive a delegate you’d plan to execute it at some point, and use it’s value in your application; you’re interested in the return value of that delegate, not where that value comes from. However, with static reflection you don’t actually care what value is returned, just where it comes from!

    Expression is a collection of classes that describe how methods are written, you can use it to interrogate a method to find any declarations, assignments, and method accesses (and more). In the same way that the reflection API is a programatic way of accessing class definitions, rather than objects; Expression is a way of accessing the contents of a method declaration, rather than the result of the evaluation of that method.

    Clear as mud? :)

    By James Gregory1 Jan, 2009 @ 10:10 am

  3. Ok, that makes sense.

    Here is my stupid question then:

    What if I wanted to get the value?

    ie. suspose I wanted to create a new asp.net mvc textbox control that didn’t use ‘magic strings’ anymore.

    ie. instead of:
    Html.TextBox(“Name”, ViewData.Model.Name) where ViewData.Model is the ‘Customer’

    Instead I’d rather have a
    Html.TextBox(c => c.Name) (or something like this)- that

    1. uses reflection to set the textbox id to ‘name’ and
    2. also sets the value

    I bring this up, after seeing the code in MvcContrib, much of it is using lamba expressions.

    Thanks again for the post, very informative – I’ll go check out the source of the links you provided to help understand this more.

    By Steve — 1 Jan, 2009 @ 1:35 pm

  4. You can do both, you can use the expression API to interrogate the structure of the lambda, and then evaluate it for it’s value.

    Expression<Func<Customer, object>> exp = c => c.Name;
    
    // get PropertyInfo (for .Name)
    var property = exp.Body as PropertyInfo;
    
    // evaluate expression for value of Name, passing in the model object
    var value = exp(ViewData.Model);
    

    Something along those lines…

    By James Gregory1 Jan, 2009 @ 1:42 pm

  5. Is there any way to access a static member using Expressions? E.g.

    class SomeClass {
    public static readonly int Field = 6;
    }

    Say there’s some method GetStaticField(Expression<Func> fieldExpression);
    then I would call
    GetStaticField(() => SomeClass.Field); analyzing this expression yields eventually a MemberExpression whose Expression is NULL and whose member is the FieldInfo corresponding to SomeClass.Field.

    What I need to do (and can’t figure out how) is to build that member expression from scratch, knowing only the field’s declaring type (== typeof(SomeClass)) and its name (== “Field”)

    By DotNetIsFun — 7 Jul, 2009 @ 6:33 am

  6. You should just need to build up the Expression objects to match the structure you analysed; if it’s possible to be given that structure, then it’s possible to create it.

    By James Gregory7 Jul, 2009 @ 7:40 am

  7. Looks like it can’t be done without reflection, which is what I wanted to avoid. I’ve tried to use Expression.Field(…) to get the MemberExpression. It has 2 overloads:

    1) Expression.Field(Expression ex, string name); “ex” is the expression which should be null (see my previous post); so I should pass null and the name of the field; well it doesn’t work – throws exception: “ex” can’t be null.

    2) Expression.Field(Expression ex, FieldInfo field). Using this I pass null for ex and the FieldInfo for my field, which I get using reflection;

    So I figured: when the member expression refers to a static member, its Expression property is always null. This means the only info regarding the target’s declaring type is kept in the Member property.

    In a more general context, there is no way to create an expression to access a static member. Please tell me that I’m wrong…

    By DotNetIsFun — 7 Jul, 2009 @ 12:32 pm

Post a comment...