Daniel Cazzulino's Blog : Statically-typed reflection with LINQ

Subscriptions

News

Source code published in this blog is public domain unless otherwise specified.

 

kzu in LinkedIn

  Microsoft MVP Profile

 Contact

Post Categories

Statically-typed reflection with LINQ

Quite some time ago I posted about how to use LINQ to provide a strong-typed reflection API. I used a very old LINQ preview back then.

With .NET 3.5 and C# 3.0 released now, it was time for an update. As part of the update, I also improved the API a little bit. Usage now is:

MethodInfo toString = Reflect.GetMethod(x => x.ToString());

The renamed Reflect<TTarget> class receives the type you want to reflect as a generic parameter. Then you can use GetMethod, GetField or GetProperty.

Other examples:

MethodInfo clone = Reflect.GetMethod(x => x.Clone());

PropertyInfo prop = Reflect.GetProperty(x => x.BaseDirectory);

FieldInfo field = Reflect.GetField(x => x.PublicField);

Working principle is the same: the lambda you pass to the methods is actually an expression which I analyze to retrieve the underlying reflection object that is already exposed by the LINQ Expression API. For example, once you get to a MethodCallExpression, you can get the method being called through its Method property:

((MethodCallExpression)lambda.Body).Method;

It's interesting to see how this works actually, and what's the compiler generating for those lambda expressions invoking methods.

In Reflector, the following C# code:

MethodInfo clone = Reflect.GetMethod(x => x.Clone());

is decompiled as (indented for readability):

ParameterExpression CS$0$0000;
MethodInfo clone = Reflect.GetMethod(
Expression.Lambda>(
Expression.Call(
      CS$0$0000 = Expression.Parameter(typeof(ICloneable), "x"), 
      (MethodInfo) methodof(ICloneable.Clone), 
new Expression[0]
    ), 
new ParameterExpression[] { CS$0$0000 }
  )
);

Note how the MethodInfo is retrieved directly from the interface by using a methodof operator. It's not a valid C# keyword, but given that Lutz Roeder works for Microsoft (not on the C# team, though), let's hope it will get eventually in the language :).

That methodof translation is actually the conversion from the following two IL lines:

L_0017: ldtoken instance object [mscorlib]System.ICloneable::Clone()
L_001c: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)

ldtoken is the key there, let's hope it gets promoted to C# in some way eventually.

Anyway, since I wrote my original article, I realized through Ayende's blog that you can also do static reflection without LINQ. It only works for methods though, and you cannot use the lambda syntax because it results in method infos that are actually from a compiler-generated type (the one that contains the closures too if any).

As I'm so in love with the lambda syntax, I'll keep my implementation based on expression trees instead of delegates.

It's released now as part of Clarius Labs projects. Get the source and have fun!

 

[License: Microsoft Permissive License (Ms-PL) v1.1]

posted on Sunday, December 30, 2007 11:45 AM by kzu

# Strong-typed reflection with LINQ @ Sunday, December 30, 2007 12:11 PM

Quite some time ago I posted about how to use LINQ to provide a strong-typed reflection API . I used

Anonymous

# Strong-typed reflection with LINQ @ Monday, December 31, 2007 10:54 AM

Bookmarked your post over at Blog Bookmarker.com!

Anonymous

# Static Reflection using Expression Trees @ Monday, December 31, 2007 4:35 PM

Static Reflection using Expression Trees

Anonymous

# Statically-typed reflection with LINQ @ Saturday, January 05, 2008 8:26 PM

Bookmarked your post over at Blog Bookmarker.com!

Anonymous

# Statically-typed reflection with LINQ @ Sunday, February 03, 2008 8:52 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Anonymous

# Exploring ShadeTree Features, Part 1: Static Reflection with ReflectionHelper @ Sunday, July 06, 2008 5:38 PM

At work, Jeremy and I have been using -- and contributing to -- some of the code he&amp;#39;s put together

Anonymous

# Strongly typed convention based mappings using Linq to Xsd - Part 1 @ Wednesday, July 28, 2010 9:40 AM

This is part 1 in a blog series about yet another method for configuring your NHibernate mappings in

Anonymous