Search code examples
c#lambdaexpression-trees

ExpressionTree as method parameter to accept any method


I need to make a method that examines dynamically method delegate passed as a parameter. But I can't force expression trees to accept any method regardless of their signature.

This is my method (doesn't compile: error CS0030: Cannot convert type 'method' to 'Delegate' )

public void Examine<T>(Expression<Func<T, Delegate>> expression2)
{
   // examine expression tree to get method name (MethodInfo)
}

I want to invoke it this way:

Examine<Foo>(x => foo1.Test1);
Examine<Bar>(x => bar2.DifferentMethod2);
// etc, with other methods

where:

  • class Foo has method: bool Test1(int num)
  • class Bar has method: 'string DifferentMethod2(string a, string b)`
  • and many others

How to achieve it?

Remark:

  • I CAN'T use Func<> or Action<> as there will be many possible method signatures that need to be accepted with parameter types I will not have a reference to.

Solution

  • You do have to use Func or Action, however you can use it on the caller side instead of the method side so you can still accept any type.

    static void Main()
    {
        Foo foo1 = null;
        Bar bar2 = null;
        Examine<Foo>(x => (Func<int,bool>)foo1.Test1);
        Examine<Bar>(x => (Func<string,string,string>)bar2.DifferentMethod2);
    }
    public static void Examine<T>(Expression<Func<T, Delegate>> expression2)
    {
        // examine expression tree to get method name (MethodInfo)
    }
    

    This creates a expression like

    .Lambda #Lambda1<System.Func`2[SandboxConsole.Foo,System.Delegate]>(SandboxConsole.Foo $x) {
        (System.Func`2[System.Int32,System.Boolean]).Call .Constant<System.Reflection.MethodInfo>(Boolean Test1(Int32)).CreateDelegate(
            .Constant<System.Type>(System.Func`2[System.Int32,System.Boolean]),
            .Constant<SandboxConsole.Program+<>c__DisplayClass0_0>(SandboxConsole.Program+<>c__DisplayClass0_0).foo1)
    }
    

    and

    .Lambda #Lambda1<System.Func`2[SandboxConsole.Bar,System.Delegate]>(SandboxConsole.Bar $x) {
        (System.Func`3[System.String,System.String,System.String]).Call .Constant<System.Reflection.MethodInfo>(System.String DifferentMethod2(System.String, System.String)).CreateDelegate(
            .Constant<System.Type>(System.Func`3[System.String,System.String,System.String]),
            .Constant<SandboxConsole.Program+<>c__DisplayClass0_0>(SandboxConsole.Program+<>c__DisplayClass0_0).bar2)
    }
    

    for the two invocations.