在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
方法,然后获取每个表达式的属性信息?
答案 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;
}