views:

362

answers:

6

Here the context for my question:

A common technique is to declare the parameter of a method as a Lambda expression rather than a delegate. This is so that the method can examine the expression to do interesting things like find out the names of method calls in the body of the delegate instance.

Problem is that you lose some of the intelli-sense features of Resharper. If the parameter of the method was declared as a delegate, Resharper would help out when writing the call to this method, prompting you with the x => x syntax to supply as the argument value to this method.

So... back to my question I would like to do the follow:

    MethodThatTakesDelegate(s => s.Length);
}

private void MethodThatTakesDelegate(Func<string, object> func)
{
    //convert func into expression
    //Expression<Func<string, object>> expr = "code I need to write"

    MethodThatTakesExpression(expr);
}


private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
    //code here to determine the name of the property called against string (ie the Length)
}
A: 

I was glossing over this blog entry and it appears to just do a direct assignment. Would that not work for you?

plinth
A: 

I don't believe it's possible to achieve what you'd like here. From the comments in your code it looks like you are attempting to capture the name of the property which did the assignment in MethodThatTakesExpression. This requires an expression tree lambda expression which captures the contexnt of the property access.

At the point you pass a delegate into MethodThatTakesDelegate this context is lost. Delegates only store a method address not any context about the method information. Once this conversion is made it's not possible to get it back.

An example of why this is not possible is that there might not even be a named method backing a delegate. It's possible to use ReflectionEmit to generate a method which has no name whatsoever and only exists in memory. It is possible though to assign this out to a Func object.

JaredPar
A: 

No, it is not possible.

Rinat Abdullin
+2  A: 

Everywhere that you're using the term "lambda expression" you actually mean "expression tree".

A lambda expression is the bit in source code which is

parameters => code

e.g.

x => x * 2

Expression trees are instances of the System.Linq.Expressions.Expression class (or rather, one of the derived classes) which represent code as data.

Lambda expressions are converted by the compiler into either expression trees (or rather, code which generates an expression tree at execution time) or delegate instances.

You can compile an instance of LambdaExpression (which is one of the subclasses of Expression) into a delegate, but you can't go the other way round.

In theory it might be possible to write such a "decompiler" based on the IL returned by MethodBase.GetMethodBody in some situations, but currently there are various delegates which can't be represented by expression trees. An expression tree represents an expression rather than a statement or statement block - so there's no looping, branching (except conditionals), assignment etc. I believe this may change in .NET 4.0, though I wouldn't expect a decompilation step from Microsoft unless there's a really good reason for one.

Jon Skeet
A: 

Thanks guys.

"At the point you pass a delegate into MethodThatTakesDelegate this context is lost."

"Lambda expressions are converted by the compiler into either expression trees"

This makes a lot of sense.

Looks like I'll just have to live without the Resharper richness :-(

Thanks all the same to everyone who responded (so quickly!)

Christian

A: 

PS. Like most people, I really enjoyed your book John! I'm taking it for a spin a second time around at the moment :-)

Glad to hear it :) Amazon reviews are always welcome (but please be honest with criticisms as well).
Jon Skeet