0

I need to be able to refer to an object's property through an Expression, which I do in this way:

Expression<Func<MyFirstModel, object>> MyFirstModelIdProperty = x => x.Id;

Intellisense is allowing me to do this, but I don't know for sure that's the correct declaration.

Now, I'm trying to actually use the property reference in a LINQ expression

int id = 500;
myFirstModelDataSet.SingleOrDefault(x=> MyFirstModelIdProperty == id); //??

Obviously, this isn't even compiling but I'm not sure how to go about.

Eventually, I'll have to also support this case

Expression<Func<MyFirstModel, object>> MyFirstModelIdProperty = x => x.Id;
Expression<Func<MySecondModel, object>> MySecondModelIdProperty = x => x.TheId;

MySecondModel secondModel = new MySecondModel() { TheId = 55 };
myFirstModelDataSet.SingleOrDefault(x=> MyFirstModelIdProperty == MySecondModelIdProperty); //??

The end goal here is that I want people to be able to inform my project how to query a DbSet by "id" without having to specify the properties literally (through strings).

Any ideas ?

Francis Ducharme
  • 4,848
  • 6
  • 43
  • 81

1 Answers1

2

Assuming your are working with IQueryable(otherwise just compile expression) - the easiest option would be to use LINQKit:

myFirstModelDataSet.AsExpandable().SingleOrDefault(x=> MyFirstModelIdProperty.Invoke(x) == (object)id);

Otherwise you will need to perform some expression tree compilation yourself:

int someId = 42;
var equalExp = Expression.Equal(MyFirstModelIdProperty.Body, Expression.Convert(Expression.Constant(someId), typeof(object)));
var expression = Expression.Lambda<Func<Person, bool>>(equalExp, MyFirstModelIdProperty.Parameters);
myFirstModelDataSet.SingleOrDefault(expression);

For the second one you will need to perform parameter replacement which can easily be done with ReplacingExpressionVisitor. Something along these lines:

var secondOp = new ReplacingExpressionVisitor(MySecondModelIdProperty .Parameters, MyFirstModelIdProperty.Parameters)
        .Visit(MySecondModelIdProperty.Body);

var equalExp = Expression.Equal(MyFirstModelIdProperty.Body, secondOp);
Guru Stron
  • 102,774
  • 10
  • 95
  • 132