在运行时通过表达式树链接方法调用

4
我希望在运行时动态构建表达式树。该表达式将调用多个方法,并将一个方法的结果传递给下一个方法,最后一个方法返回某些内容。我可以轻松地构建和运行单个方法调用表达式,但无法弄清如何在 Expression 中链接这些方法。
以下是简化后的代码。实际代码具有可变数量的方法调用和参数。
从概念上讲,我正在尝试通过组合 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";
        }
    }
}

HostNumber.GetHostNumber("Bleacher").HostStatus.GetHostStatus()无法编译,因为GetHostNumber返回一个整数,而不是具有HostStatus属性的对象。 - Yacoub Massad
我知道。我只是添加了那一行来展示我想要实现的概念。HostNumber.GetHostNumber("Bleacher")的输出值(45)应该被传递给HostStatus.GetHostStatus()。谢谢。 - Canacourse
1个回答

3
以下是您可以实现的方法:

这里是如何做到的:

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();

顺便说一下,我不清楚你为什么这样做。 为什么要构建静态表达式然后进行编译?


可以了,谢谢。这些方法调用是从配置文件(DSL)中解析出来的。 - Canacourse
你好。我明白了。所以它是动态的,因为方法名称不是静态的。 - Yacoub Massad
是的,但表达式可能包含一个方法调用或多达三个方法调用,并且方法调用可能没有参数或最多有两个参数。因此,您的代码可能会变得复杂。我曾尝试使用表达式访问器将表达式合并在一起,但在途中迷失了方向。 - Canacourse
1
看一下LINQKit,它可能会帮助你完成你想要做的事情。它允许你在一个表达式中使用另一个表达式,然后扩展结果以创建一个真正的组合表达式。但我不确定它是否适用于你的情况。 - Yacoub Massad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接