3

I am having to generically build a comparative predicate for an Entity Framework Linq query. I'm using reflection and am able to build a single level Lambda expression without any trouble. However where I am starting to get stuck is I have an Entity that has a relationship

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.....
}

How can I can I pass in "Child.property" into Reflection to be able to create a lambda expression comparing and come up with a lambda expression similar to item => item.Child.property == value?

UnHoly Ram
  • 157
  • 1
  • 9

2 Answers2

3

I think you are looking for this:

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());
Aducci
  • 26,101
  • 8
  • 63
  • 67
3

I assume you are wanting a generic solution supporting nested properties:

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);
}
Bob Vale
  • 18,094
  • 1
  • 42
  • 49
  • This works. How would you handle it for a collection? – Kenci Oct 14 '15 at 12:11
  • @Kenci as in using property indexing? `Wibble[5].Value` – Bob Vale Oct 14 '15 at 15:42
  • What I meant was what if the OP's Child property was a collection, and you wanted to wrap a "contains" around that collection so that your lambda would be something like: Parent.Where(x => someList.Contains(x.property); – Kenci Oct 15 '15 at 08:17
  • @Kenchi then you would need to replace the Expression.Equal call. You would need to construct a method invocation of the Contains method – Bob Vale Oct 20 '15 at 11:37
  • @Kenci the hard part is you would need to know if you were calling contains on the collection itself or utilizing the linq Contains method. – Bob Vale Oct 20 '15 at 11:38