Canacourse
Canacourse

Reputation: 1865

Chaining method calls in Expression Tree at runtime

I am looking to build an expression tree dynamically at runtime. The expression will call several methods and pass the result of one method to the next with the last method returning something. I can build and run single method call expressions without difficulty but cannot figure out how to chain these methods together in an Expression.

Simplified code below. The live code has methods with variable number of method calls and params.

Conceptually I'm trying to get the equivalent to this at runtime by combining expression1 & expression2

var uncompileable = HostNumber.GetHostNumber("Bleacher").HostStatus.GetHostStatus(); // Status = "Online"

using System;
using System.Linq.Expressions;

namespace SO
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            ConstantExpression param1 = Expression.Constant(Convert.ChangeType("Bleacher", typeof(String)));      
            MethodCallExpression expression1 = Expression.Call(typeof(HostNumber), "GetHostNumber", null, new Expression[] { param1 });

            ConstantExpression param2 = Expression.Constant(Convert.ChangeType("45", typeof(int)));
            MethodCallExpression expression2 = Expression.Call(typeof(HostStatus), "GetHostStatus", null, new Expression[] { param2 });

            var invokee = Expression.Lambda(expression1).Compile();
            var result = invokee.DynamicInvoke();

        }
    }

    public class HostNumber
    {
        public static int GetHostNumber(string hostName)
        {
            return 45;
        }
    }

    public static class HostStatus
    {
        public static string GetHostStatus(int hostNumber)
        {
            return "Online";
        }
    }
}

Upvotes: 5

Views: 2419

Answers (1)

Yacoub Massad
Yacoub Massad

Reputation: 27861

Here is how you would do it:

var expression =
    Expression.Call(
        typeof (HostStatus).GetMethod("GetHostStatus", BindingFlags.Public | BindingFlags.Static),
        Expression.Call(
            typeof (HostNumber).GetMethod("GetHostNumber", BindingFlags.Public | BindingFlags.Static),
            Expression.Constant("Bleacher", typeof (string))));

var func = Expression.Lambda<Func<string>>(expression).Compile();

var result = func();

By the way, it is not clear to me why are you doing this. Why are you building a static expression and then compile it?

Upvotes: 4

Related Questions