使用反射在通用/动态linq谓词中比较子属性

3

我需要通用地构建一个比较谓词,用于Entity Framework Linq查询。我正在使用反射技术,能够轻易地构建单层Lambda表达式。但是现在我遇到了困难,因为我的实体有一些关联。

public class Parent {
    public virtual Child child { get; set; }
    .... Other Stuff...
}

public class Child {
    public int property { get; set; }
    public virtual Parent parent { get; set; }
    .... Other Stuff.....
}

我该如何将"Child.property"传递给反射中,以便能够创建一个比较lambda表达式,并得出类似于item => item.Child.property == value的lambda表达式?
2个回答

3
我想这是您要找的内容:
ParameterExpression parameter = Expression.Parameter(typeof(Parent), "item");
Expression child = Expression.PropertyOrField(parameter, "child");
Expression childProperty = Expression.PropertyOrField(child, "property");
int value = 1;
Expression comparison = Expression.Equal(childProperty, Expression.Constant(value));

Expression<Func<Parent, bool>> lambda = Expression.Lambda<Func<Parent, bool>>(comparison, parameter);


var sample = new[] { new Parent() { child = new Child() { property = 1 } } };
var result = sample.Where(lambda.Compile());

3

我猜您想要一个支持嵌套属性的通用解决方案:

public Expression buildLambda(Type startingType, string propertyPath, object value) {

  var parameter=Expression.Parameter(startingType,"item");
  var valueExpression = Expression.Constant(value);
  var propertyExpression=propertyPath.Split('.').Aggregate(parameter,(Expression parent,string path)=>Expression.Property(parent,path));
  return Expression.Lambda(Expression.Equal(propertyExpression,valueExpression),parameter);
}

这个可以。你如何处理一个集合? - Kenci
@Kenci,是指使用属性索引吗?Wibble[5].Value - Bob Vale
我的意思是,如果OP的Child属性是一个集合,而你想要在该集合周围包装一个“包含”,使得你的lambda表达式看起来像这样:Parent.Where(x => someList.Contains(x.property); - Kenci
@Kenchi 那么你需要替换 Expression.Equal 调用。你需要构造一个包含 Contains 方法的方法调用。 - Bob Vale
@Kenci,难点在于你需要知道你是在调用集合本身的contains方法还是利用linq中的Contains方法。 - Bob Vale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接