Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the logic from one lambda within a second lambda

Tags:

c#

.net

lambda

I've looked at the other questions around this and I just can't work out how to apply the answers to my particular situation. Say you have a couple of models that look like this:

public class Person
{
    public int PersonId { get; set; }
}

public class Business
{
    public int BusinessId { get; set; }
}

I want to be able to write a couple of different generic methods: one that gets the models using a provided Lambda that might look something like this:

GetWhere(p => p.PersonId == 1)

And one to get the models using a unique key - to make this flexible, I'd like to be able to specify the unique key using a Lambda:

GetByUniqueKey(p => p.PersonId, 1)

Or

GetByUniqueKey(b => b.BusinessId, 1)

Ideally GetByUniqueKey would just be a shorthand method to build up an expression to send to GetWhere, and then return the FirstOrDefault() result. But the logic to do this is completely escaping me. What I want to do:

public IEnumerable<TModel> GetWhere(Expression<Func<TModel, bool>> whereExpression)
{
    // Get from DB using expression provided
}

public TModel GetByUniqueKey<TUniqueKey>(
         Expression<Func<TModel, TUniqueKey>> uniqueKeyProperty,
         TUniqueKey value)
{
    return GetWhere(m => uniqueKeyProperty(m) == value).FirstOrDefault();
}

So I want to take the uniqueKeyProperty expression, invoke it on the supplied parameter somehow to get the property, and then use that property in the whereExpression expression.

A note on duplicate questions: I know this looks like a duplicate of other similar questions, but please note I have read those and I just can't figure out how to apply those answers to my specific use case.

Some clarification in response to comments:

Put simply, I want to do the following:

I want to take the Expression p => p.PersonId and the value 1, and generate a whereExpression that looks like this p => p.PersonId == 1. (Thanks @Rob)

like image 460
Nick Coad Avatar asked Nov 10 '22 09:11

Nick Coad


1 Answers

You can build a new expression from the key selector and value provided like so:

public TModel GetByUniqueKey<TUniqueKey>(
    Expression<Func<TModel, TUniqueKey>> uniqueKeySelector,
    TUniqueKey value)
{
    return GetWhere(Expression.Lambda<Func<TModel,bool>>(
        Expression.MakeBinary(
            ExpressionType.Equal,
            uniqueKeySelector.Body,
            Expression.Constant(value, typeof(TUniqueKey))),
        uniqueKeySelector.Parameters));
}

For querying by ID I wouldn't bother with this approach. Check out the other static methods on the Expression class.

like image 157
pmccloghrylaing Avatar answered Nov 14 '22 22:11

pmccloghrylaing