如何在 C# 中使用 LinqExpression 创建一个动态获取 属性 的表达式?

How to create an expression getting a property dynamically using LinqExpression in c#?

我正在尝试创建一个 linq 表达式,根据 SearchFilter 对象参数从 Student 对象动态获取 属性。

问题是 Expression.Property(expr, string) 要求 属性 名称的字符串。而且我无法从 ParameterExpression 中检索字符串。我尝试了这个,但我被卡住了......作为(字符串)当然的演员阵容不起作用。关于如何继续的任何线索?

检查下面的代码:

using System;
using System.Linq.Expressions;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            var student = new Student
            {
                FirstName = "John",
                Address = new Address
                {
                    City = "New York",
                    ZipCode = 10005
                }
            };
            var filter = new SearchFilter
            {
                Rule = "ZipCode"
            };

            var studentParamExpr = Expression.Parameter(typeof(Student), "s");
            var filterParamExpr = Expression.Parameter(typeof(SearchFilter), "filter");
            var lambdaExpr = Expression.Lambda(
                CreateStudentAddressRuleAccessor(studentParamExpr, filterParamExpr),
                new ParameterExpression[] { studentParamExpr, filterParamExpr });
            var expression = lambdaExpr.Compile().DynamicInvoke(student, filter);
        }

        public static Expression CreateStudentAddressRuleAccessor(ParameterExpression student, ParameterExpression filter)
        {
            var ruleExpr = Expression.Property(filter, "Rule");
            string rule = (string)ruleExpr;

            var resultExpr = Expression.Property(Expression.Property(student, "Address"), rule);
            return resultExpr;
        }
    }

    public class Student
    {
        public string FirstName { get; set; }

        public Address Address { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public int ZipCode { get; set; }
    }

    public class SearchFilter
    {
        public string Rule { get; set; }
    }
}

Lambda 主体不要求所有参数都是表达式。 从 lambda 参数列表中删除过滤器并将过滤器 arg 的类型更改为 SearchFilter,如下所示:

static void Main(string[] args)
{
   ...
   var studentParamExpr = Expression.Parameter(typeof(Student), "s");
   var lambdaExpr = Expression.Lambda(
      CreateStudentAddressRuleAccessor(studentParamExpr, filter),
                new ParameterExpression[] { studentParamExpr });
   var expression = lambdaExpr.Compile().DynamicInvoke(student);
   Console.WriteLine($"Lambda expression = {lambdaExpr}");
   Console.WriteLine($"Expression = {expression}");
}

public static Expression CreateStudentAddressRuleAccessor(ParameterExpression student, SearchFilter filter)
{
   var resultExpr = Expression.Property(Expression.Property(student, "Address"), filter.Rule);
   return resultExpr;
}