【问题标题】:Expression tree for a member access of depth > 1深度 > 1 的成员访问的表达式树
【发布时间】:2012-06-23 08:23:01
【问题描述】:
public class Job
{
    public string Name { get; set; }
    public int Salary { get; set; }
}
public class Employee
{
    public string Name { get; set; }
    public Job Job { get; set; }
}

如果我想创建一个成员访问 Employee.Name 的表达式树,这就是我要做的:

        var param = Expression.Parameter(type, "x");
        var memberAccess = Expression.PropertyOrField(param, memberName);
        return Expression.Lambda<Func<TModel, TMember>>(memberAccess, param);

对于访问 Employee.Job.Salary 的成员来说,这相当于什么?

【问题讨论】:

  • 我已经尝试使用我创建的 memberAccess 并在其上创建另一个 memberAccess:Expression.PropertyOrField(baseMemberAccess, memberName),但它不起作用,它尝试在基础中找到 memberName成员访问函数

标签: c# linq lambda expression expression-trees


【解决方案1】:

你需要:

var jobProperty = Expression.PropertyOrField(param, "Job");
var salaryProperty = Expression.PropertyOrField(jobProperty, "Salary");

基本上,您从评估x.Job 的结果中获取Salary 属性。

如果您需要以编程方式执行此操作,则需要以下内容:

Expression expression = Expression.Parameter(type, "x");
foreach (var property in properties.Split('.'))
{
    expression = Expression.PropertyOrField(expression, property);
}

【讨论】:

    【解决方案2】:

    最好的方法是创建扩展as here:

    public static class ExpressionExtensions
    {
        /// <summary>
        ///     create expression by property name
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="propertyName">
        ///     <example>Urer.Role.Name</example>
        /// </param>
        /// <returns></returns>
        public static Expression<Func<TModel, dynamic>> CreateExpression<TModel>(this string propertyName) {
            Type currentType = typeof (TModel);
            ParameterExpression parameter = Expression.Parameter(currentType, "x");
            Expression expression = parameter;
    
            int i = 0;
            List<string> propertyChain = propertyName.Split('.').ToList();
            do {
                System.Reflection.PropertyInfo propertyInfo = currentType.GetProperty(propertyChain[i]);
                currentType = propertyInfo.PropertyType;
                i++;
                if (propertyChain.Count == i)
                {
                    currentType = typeof (object);
                }
                expression = Expression.Convert(Expression.PropertyOrField(expression, propertyInfo.Name), currentType);
            } while (propertyChain.Count > i);
    
            return Expression.Lambda<Func<TModel, dynamic>>(expression, parameter);
        }
    }
    

    您不能每次都将 Convert() 转换为 typeof(object),因为 System.Object 没有您的类型所具有的属性(例如您的示例中的 Name 或 Salary)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      相关资源
      最近更新 更多