如何动态创建包含点表示法的 Lambda 表达式

本文关键字:表示 Lambda 表达式 包含点 创建 何动态 动态 | 更新日期: 2023-09-27 18:31:54

我今天有一个方法,该方法基于字符串属性名称返回lambda表达式,即我传入"描述",它返回d => d.Description的lambda。 这很好用,但现在我需要返回一个 lambda 表达式,给定一个包含点符号的字符串,即我想传递"Customer.Name"并得到一个 lambda 表达式返回 d => d.Customer.Name。 下面是我已经创建的方法,它返回 1 级 lambda,但我不确定如何将其更改为多级。

protected dynamic CreateOrderByExpression(string sortColumn)
{
    var type = typeof (TEntity);
    Type entityType = null;
    if (type.IsInterface)
    {
        var propertyInfos = new List<PropertyInfo>();
        var considered = new List<Type>();
        var queue = new Queue<Type>();
        considered.Add(type);
        queue.Enqueue(type);
        while (queue.Count > 0)
        {
            var subType = queue.Dequeue();
            foreach (var subInterface in subType.GetInterfaces().Where(subInterface => !considered.Contains(subInterface)))
            {
                considered.Add(subInterface);
                queue.Enqueue(subInterface);
            }
            var typeProperties = subType.GetProperties(
                BindingFlags.FlattenHierarchy
                | BindingFlags.Public
                | BindingFlags.Instance);
            var newPropertyInfos = typeProperties
                .Where(x => !propertyInfos.Contains(x));
            propertyInfos.InsertRange(0, newPropertyInfos);
            if (propertyInfos.All(f => f.Name != sortColumn)) continue;
            entityType = subType;
            break;
        }
    }

    if (entityType == null)
    {
        return null;
    }
    var parameter = Expression.Parameter(typeof (TEntity));
    var memberExpression = Expression.Property(parameter, entityType, sortColumn);
    var lambdaExpression = Expression.Lambda(memberExpression, parameter);
    return lambdaExpression;
}

如何动态创建包含点表示法的 Lambda 表达式

创建一个这样的帮助程序方法(在代码的底部使用):

LambdaExpression GetLambdaExpression(Type type, IEnumerable<string> properties)
{
  Type t = type;
  ParameterExpression parameter = Expression.Parameter(t);
  Expression expression = parameter;
  for (int i = 0; i < properties.Count(); i++)
  {
    expression = Expression.Property(expression, t, properties.ElementAt(i));
    t = expression.Type;
  }
  var lambdaExpression = Expression.Lambda(expression, parameter);
  return lambdaExpression;
}

现在像这样使用它:

GetLambdaExpression(typeof(Outer), new[] { "InnerProperty", "MyProperty" });

对于以下类:

class Outer
{
    public Inner InnerProperty { get; set; }
}
class Inner
{
    public int MyProperty { get; set; }
}

我知道它可能更适合您的原始代码,但我想您可以从这里开始(例如将带有点的字符串转换为数组)。我知道这本来可以使用递归来完成,但我今天很头疼......