如何将多个lambda表达式传递给一个方法,然后获取每个表达式的属性信息?

时间:2019-03-04 18:32:44

标签: c# lambda

在C#项目中,我想创建一个函数,该函数允许我传递lambda表达式,该表达式可以将每个表达式解析为PropertyInfo,在其中可以提取属性名称和属性值。

这是我的代码的精简版

 <thymeleaf-layout-dialect.version>2.2.1</thymeleaf-layout-dialect.version>

当我将原始类型的属性传递给函数时, <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring3</artifactId> <version>3.0.9.RELEASE</version> </dependency> 失败,因为public IEnumerable<Student> Make(IEnumerable<User> users, Expression<Func<User, dynamic>> primaryProperty, params Expression<Func<User, dynamic>>[] otherProperties) { var students = new List<Student>(); foreach(User user in users) { var student = new Student(); var mainProp = GetPropertyInfo(user, primaryProperty); object mainValue = prop.GetValue(user, null); // Do somthing with mainProp.Name... // Do something with mainValue ... foreach(Expression<Func<User, dynamic> exp in otherProperties ?? new Expression<Func<User, dynamic>>[] {}) { var prop = GetPropertyInfo(user, exp); object value = prop.GetValue(user, null); // Set the property student property // Do somthing with prop.Name... // Do something with value... } students.Add(student); } return strudents; } private static PropertyInfo GetPropertyInfo<TSource, TProperty>(TSource source, Expression<Func<TSource, TProperty>> propertyLambda) { Type type = typeof(TSource); if (!(propertyLambda.Body is MemberExpression expression)) { throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property."); } PropertyInfo propInfo = expression.Member as PropertyInfo; if (propInfo == null) { throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property."); } if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType)) { throw new ArgumentException($"Expression '{propertyLambda}' refers to a property that is not from type {type}."); } return propInfo; } 返回null。

从Google看来,造成此问题的原因是因为我使用GetPropertyInfo作为该函数的返回值,而该函数应该类似于propertyLambda.Body as MemberExpression expression。这是参考文献Expression.Body as MemberExpression returns null for primitive property

但是,我不确定如何重写我的dynamic方法以使用TProperty而不是Make每个属性可以具有不同的类型。

问题:如何将多个lambda表达式传递给TProperty方法,然后获取每个表达式的属性信息?

1 个答案:

答案 0 :(得分:0)

在表达式类型中使用object代替dynamic应该没问题。

public IEnumerable<Student> Make(IEnumerable<User> users, Expression<Func<User, object>> primaryProperty, params Expression<Func<User, object>>[] otherProperties)

要注意的是,您的表达式主体很可能会被包装在Convert表达式中,这表示您的属性正在隐式转换为对象。因此,您可能需要在GetPropertyInfo方法中使用类似这样的代码。

var expressionBody = propertyLambda.Body;
if (expressionBody is UnaryExpression expression && expression.NodeType == ExpressionType.Convert)
{
    expressionBody = expression.Operand;
}