Put it together, then break it apart

Ian recently posted a question on how to make data-binding more type safe. While looking at his original solution, I realised how nice the new lambda expressions of C# are. They are typechecked, giving the programmer some safety, and can be decomposed.
Given a class like the following, we can represent the data binding against the Foo property using a lambda () => instance.Foo. This lambda is typechecked so we will get compile time errors if we try to use an unknown property.

public class A
public int Foo
return 20;

Then later we can take this lambda expression apart to get the instance and the property information.

A instance1 = new A();
Expression<Func<int>> theFunction = () => instance1.Foo;

A instance2;
PropertyInfo property;
A>(theFunction, out instance2, out property);

This method to extract the instance and property can be easily written as:

static void ExtractTargetAndProperty<T>(Expression<Func<int>> xx, out T thisPointer, out System.Reflection.PropertyInfo member)
MemberExpression exp = (MemberExpression) xx.Body;
Expression thisValue = exp.Expression;
Expression<Func<T>> getThis = Expression.Lambda<Func<T>>(thisValue, null);
Func<T> thisFetcher = getThis.Compile();
  thisPointer = thisFetcher();
  member = (System.Reflection.
PropertyInfo) exp.Member;

The need to wrap the expression with a () => to delay the evaluation isn’t as tidy as I’d like. In languages like Common Lisp, macros are a great way to get the wrapping automatically added. Maybe we’ll get them in C# one day.

This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s