I am trying to have MethodCallExpression compiled with a lambda expression. Basically i want a method to be called everytime the lambda expression is invoked.
I am not sure i'm even on the right path but so far i got,
public Func<T, TResult> Get<T, TResult>(Object obj, Action<object> action = null)
{
Expression<Func<T, TResult>> lambda = GetLambdaExpression<T, TResult>(obj);
var parameterValue = action.Method.GetParameters().Single();
var callback = Expression.Call(Expression.Constant(action.Target), action.Method, Expression.Constant(parameterValue));
return lambda.Compile();
}
I need to somehow combine the lambda and the action callback and compile them into a Func<T, TResult>
. Something like this:
obj => { action(obj); return lambda(obj); }
I am trying to have MethodCallExpression compiled with a lambda expression. Basically i want a method to be called everytime the lambda expression is invoked.
I am not sure i'm even on the right path but so far i got,
public Func<T, TResult> Get<T, TResult>(Object obj, Action<object> action = null)
{
Expression<Func<T, TResult>> lambda = GetLambdaExpression<T, TResult>(obj);
var parameterValue = action.Method.GetParameters().Single();
var callback = Expression.Call(Expression.Constant(action.Target), action.Method, Expression.Constant(parameterValue));
return lambda.Compile();
}
I need to somehow combine the lambda and the action callback and compile them into a Func<T, TResult>
. Something like this:
obj => { action(obj); return lambda(obj); }
Share
Improve this question
edited Feb 7 at 0:24
Ivan Petrov
4,5452 gold badges11 silver badges23 bronze badges
asked Feb 6 at 18:35
Dexter MorganDexter Morgan
12710 bronze badges
7
|
Show 2 more comments
1 Answer
Reset to default 2Judging from the comments under the question, I think you are after this:
// Example values for obj/Action params
// and what GetLambdaExpression would return from your code
object obj = 42;
Action<object> action = (ob) => Console.WriteLine($"Action on {ob}");
Expression<Func<int, int>> lambda = a => a + 3;
// actual logic
// this is for the unlikely case that action has
// other callbacks chained via += and we want all of them to
// uncomment next line to demo
// action += (ob) => Console.WriteLine("AnotherAction on" + ob);
var invokeMethodInfo = typeof(Action<object>).GetMethod("Invoke");
var lambdaParam = lambda.Parameters.FirstOrDefault();
var lambdaParmCastObject = Expression.Convert(lambdaParam, typeof(object));
var actionMethodcallExpression = Expression.Call(Expression.Constant(action),
invokeMethodInfo, lambdaParmCastObject);
var body = Expression.Block(actionMethodcallExpression,
Expression.Invoke(lambda, lambdaParam));
var newLambda = Expression.Lambda<Func<int, int>>(body, lambdaParam);
// Testing code
var compiled = newLambda.Compile();
Console.WriteLine("Invoking");
int result = compiled(3);
Console.WriteLine($"Result of Lambda: {result}");
Output:
Invoking
Action on 3
Result of Lambda: 6
GetLambdaExpression
return? What exactly do you want to happen? – Charlieface Commented Feb 6 at 18:51obj => { var o = lambda(obj); action(o); return obj; }
or maybeobj => { action(obj); return lambda(obj); }
– Charlieface Commented Feb 6 at 19:12X
problem you're solving by "trying to have MethodCallExpression compiled with a lambda expression"? – IV. Commented Feb 6 at 19:15var func = lambda.Compile(); return obj => { action(obj); return func(obj); }
– Charlieface Commented Feb 7 at 2:05