I am trying to generate expression like (Foo foo) => () => foo.Bar()
, and then run the outer lambda providing the Foo
instance, so that returned value would be a closure which statically calls Foo.Bar
, to avoid implicit exception catching introduced by the dynamic call.
However, calling the outer expression fails with exception "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined".
Am I making some mistake or there is some conceptual reason preventing it?
The minimal full code:
using System;
using System.Linq.Expressions;
namespace ConsoleApp2 {
class Program {
static void Main(string[] args)
{
// supposed to be "(Foo foo) => () => foo.Bar()",
// inspecting `expr` in debugger seems to agree
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(Expression.Variable(typeof(Foo), "foo"), typeof(Foo).GetMethod("Bar"))),
new[] { Expression.Variable(typeof(Foo), "foo") });
// here exception "variable 'foo' of type 'ConsoleApp2.Foo' referenced from scope '', but it is not defined" is thrown
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
You need to make sure that the variable expressions in the lambda expression reference the same instance.
This code runs just fine, and seems to give the expected result.
void Main()
{
var var = Expression.Variable(typeof(Foo), "foo");
var expr = Expression.Lambda(
Expression.Lambda(
Expression.Call(var, typeof(Foo).GetMethod("Bar"))), new[] { var });
var res = (Action)expr.Compile().DynamicInvoke(new Foo());
res();
}
class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With