Click here to Skip to main content
15,867,488 members
Articles / Programming Languages / C#

Invoke a Lambda Function through Reflection

Rate me:
Please Sign up or sign in to vote.
4.82/5 (11 votes)
10 Aug 2010CPOL2 min read 38.5K   251   21   6
How to call a strongly-typed lambda function with reflection

Introduction

At work, I was writing a small library for a customer - in this library, you are able to setup strongly-typed seaching objects that use lambda expressions to search through a domain model.

All-in-all, a nice little library that worked fast and was easy to use. But I came across a problem when I needed to combine two or more search-objects. It is a small article that shows you how you can invoke a generic lambda function through reflection.

Background

If you have the following class defined in your domainmodel:

C#
public class LambdaClass<T>
{
    public Func<T, bool> TestMethod { get; set; }

    public LambdaClass(Func<T, bool> testMethod)
    {
        TestMethod = testMethod;
    }
} 

You can use this class like this:

C#
LambdaClass<string> lambdaTest = 
                    new LambdaClass<string>(entry => entry.Contains("Tom"));

if (lambdaTest.TestMethod("My name is Tom")) {
    Console.WriteLine("Yes it is"); 
}

This is all fine - but what if I need to call the TestMethod on the LambdaClass but I don't know the generic type?!

Using the Code

It is possible and to do this, but we have to introduce a new interface for all of this to work properly - we need to make a little abstraction and have the possibility to get the generic type.

If we introduce this interface:

C#
public interface ILambdaClass
{
    Type GetImplementedType { get; }
}

And then get our LambdaClass to implement this interface like this:

C#
public class LambdaClass<T> : ILambdaClass
{
    public Func<T, bool> TestMethod { get; set; }

    public LambdaClass(Func<T, bool> testMethod)
    {
        TestMethod = testMethod;
    }

    public Type GetImplementedType 
    {
        get
        {
            return typeof(T);
        }
    } 
}

It is now possible for use to get the generic type of the LambdaClass instance, and with this in hand, we can use reflection to create the strongly-typed type via reflection and then call the lambda expression:

C#
// Get the generic type of the lambdaClass
Type lambdaClassType = typeof(LambdaClass<>)
        .MakeGenericType(
            ((ILambdaClass)lambdaTest).GetImplementedType
         );
         
// Create the lambdafunction type by using the generic type
Type lambdaFunc = typeof(Func<,>)
        .MakeGenericType(
            ((ILambdaClass)lambdaTest)
                .GetImplementedType, 
            typeof(bool)
         );
         
// Get the actual lambda expression from the object instance
var testMethodProperty = lambdaClassType
        .InvokeMember(
            "TestMethod", 
            System.Reflection.BindingFlags.GetProperty, 
            null, 
            lambdaTest, 
            null);
            
// Now we call Invoke on the actual lambda expression to invoke the method
// given the correct type and parameters
bool success = (bool)lambdaFunc
        .InvokeMember(
            "Invoke", 
            System.Reflection.BindingFlags.InvokeMethod, 
            null, 
            testMethodProperty, 
            new object[] { "My name is Tom" }
         );
         
if (success)
{
    Console.WriteLine("Yes it is");
}

The Dynamic Way

All of this is a lot of code and there is actually a better way of doing this - at least what this code is doing. If you know the name of the method you want to call and the exact number of parameters, you can use dynamic instead.

This small piece of code does exactly the same:

C#
dynamic lambdaDyn = lambdaTest;
if (lambdaDyn.TestMethod("My name is Tom"))
{
    Console.WriteLine("Yes it is");
} 

A lot lesser code, cleaner and just as safe - if you can do it in .NET 4.0.

Comment

Calling generic lambda Func<,> expression through reflection can be quite difficult, but when you dig down into it is not that difficult. And if you can - try to use dynamic instead - that is my lesson.

History

  • 10th August, 2010: First revision

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Dwarf A/S
Denmark Denmark
Senior lead developer and development manager for our Microsoft development department at Dwarf A/S.

Have worked on many different kind of projects and uses .NET on a daily basis.

Comments and Discussions

 
GeneralMy vote of 4 Pin
S.P.Tiwari7-Dec-11 18:12
professionalS.P.Tiwari7-Dec-11 18:12 
QuestionWhere would you need this? Pin
Nish Nishant14-Aug-10 4:47
sitebuilderNish Nishant14-Aug-10 4:47 
GeneralUse GetGenericArguments! Pin
Moim Hossain10-Aug-10 9:58
Moim Hossain10-Aug-10 9:58 
GeneralRe: Use GetGenericArguments! Pin
brianclemmensen10-Aug-10 21:52
brianclemmensen10-Aug-10 21:52 
GeneralRe: Use GetGenericArguments! Pin
Moim Hossain11-Aug-10 1:12
Moim Hossain11-Aug-10 1:12 
GeneralRe: Use GetGenericArguments! Pin
Moim Hossain11-Aug-10 1:18
Moim Hossain11-Aug-10 1:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.