views:

277

answers:

2

You can use Lambda Expression Objects to represent a lambda as an expression.

How do you create a Lambda Expression Object representing a generic method call, if you only know the type -that you use for the generic method signature- at runtime?

For example:

I want to create a Lambda Expression Objects to call: public static TSource Last<TSource>( this IEnumerable<TSource> source )

But I only know what TSource is at runtime.

+2  A: 
static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>()
{
    var source = Expression.Parameter(
        typeof(IEnumerable<T>), "source");

    var call = Expression.Call(
        typeof(Enumerable), "Last", new Type[] { typeof(T) }, source);

    return Expression.Lambda<Func<IEnumerable<T>, T>>(call, source)
}

or

static LambdaExpression CreateLambda(Type type)
{
    var source = Expression.Parameter(
        typeof(IEnumerable<>).MakeGenericType(type), "source");

    var call = Expression.Call(
        typeof(Enumerable), "Last", new Type[] { type }, source);

    return Expression.Lambda(call, source)
}
dtb
Hi DTB, pretty elegant, It's possible do the same using MakeGenericType? nice solution +1
SDReyes
@SDReyes: can you elaborate? What do you want to do with MakeGenericType?
dtb
@DTB, Hi DTB! of course : ). I'm working with reflection and I get the type to make the invocation at runtime -the type I would pass to CreateLambda<T> : |-. So I wonder, how could I do something similar to your approach without knowing the type at compile time? thanks, SD.
SDReyes
@SDReyes: I've added a version that doesn't require the type to be known at compile-time.
dtb
@DTB Wow, it looks really simple! Thank you DTB, it is exactly what I was trying to do : ) Great solution.
SDReyes
+1  A: 

I don't fully understand the question, but the code that dtb wrote could be written simply as:

class MyUtils {
  public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() { 
    return source => source.Last();
  }
}

The code in the sample by dtb is pretty much the same thing as what the C# compiler automatically generates for you from this lambda expression (compiled as expression tree, because the return type is Expression).

If you know the type at runtime, then you can either use the solution by dtb or you can invoke the CreateLambda method (above) using Reflection, which may be slower, but allows you to write the code in the lambda in the natural C#:

var createMeth = typeof(MyUtils).GetMethod("CreateLambda");
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke();

The nice thing about this approach is that the code in CreateLambda can be much more complicated, which would be really hard to do using expression trees explicitly.

Tomas Petricek
Hi Tomas! I need to improve my programming communication skills I know, I know hahahha (but don't worry I'm working on it : ). I updated the question to represent what I really meant. Nice refactor! +1
SDReyes
@SDReyes: "at runtime" was the important point. You can still use the nice C# syntax for this though (without explicitly constructing expression trees). See my updated answer.
Tomas Petricek
@Tomas: Hi Tomas!, I agree with you. this approach let you implement easily complex lambdas inside the CreateLambda method (with just a performance tradeoff). I'm gonna use the dtb approach this time, because we are already using lots of expressions in the component we're working on, and I want to keep coherence among the code : ). but I'm going to be glad to implement yours in next scenarios too! Nice job Tomas! regards. SD
SDReyes