6

how can I get a body from function

Func<bool> methodCall = () => output.SendToFile(); 

if (methodCall())
    Console.WriteLine("Success!");

I need to get this output.SendToFile() as a string

Another example:

string log = "";

public void Foo<T>(Func<T> func)
{
    try
    {
        var t = func();
    }
    catch (Exception)
    {
        //here I need to add the body of the lambda
        // log += func.body;
    }
}

public void Test()
{
    var a = 5;
    var b = 6;
    Foo(() => a > b);
}

Edit: For more information on this topic see: Expression Trees

MikeLimaSierra
  • 799
  • 2
  • 11
  • 29
Sergey
  • 180
  • 1
  • 9
  • 1
    I don't quite understand what you are asking. Do you want a method you can pass "methodCall" into and have it return "output.SendToFile()"? What should it return for other methods, like `Console.WriteLine`? – Jens Jul 16 '13 at 10:18
  • I just need to get this info from lambda "output.SendToFile()" this data I can add to the log, if I'll get an exception – Sergey Jul 16 '13 at 10:25
  • Could you do exception handling and logging inside SendToFile? The method should also be at the top of the exception stack trace (which you should maybe log anyway). – Jens Jul 16 '13 at 10:28
  • Please, confirm that Daniel answered your question or clarify what you need. Do you mean that you want the WriteLine to be within the body of the lambda expression? That's how I understood it first. – Tarik Jul 16 '13 at 10:29
  • Do you mean that you want the WriteLine to be within the body of the lambda expression? That's how I understood it first. – Tarik Jul 16 '13 at 10:39
  • 1
    Sorry if mislead, in second example I need to have "a >b" as a string – Sergey Jul 16 '13 at 10:41

1 Answers1

12

You can't. A Func<T> is nothing you can easily analyze. If you want to analyze a lambda, you need to create a Expression<Func<bool>> and analyze it.

Getting the body of an expression is simple:

Expression<Func<bool>> methodCall = () => output.SendToFile(); 
var body = methodCall.Body;

body would be a MethodCallExpression you could further analyze or just output via ToString. Using ToString won't result exactly in what you would like to have, but it contains that information, too.

For example, executing ToString() on body in LINQPad results in something like this:

value(UserQuery+<>c__DisplayClass0).output.SendToFile()

As you can see, "output.SendToFile()" is there.

To actually execute the code defined by an expression, you first need to compile it:

var func = methodCall.Compile();
func();

Which can be shortened to this:

methodCall.Compile()(); // looks strange but is valid.
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443