Search code examples
c#.netlambda.net-coreexpression-trees

Converting expression to another?


I have a little challenge which I don't know how to solve.

I need to convert from this Expression<Func<TEntity, URequest, bool>> to this Expression<Func<TEntity, bool>>.

The 2nd is going to be used to query a data source.

The idea is this having a base class constructor with the following signature

abstract class Base
{
    Base(Expression<Func<TEntity, TRequest, bool>> expression) { .... }
}

I can provide an expression in the derived something like this

class Derived : Base 
{
   Derived() : 
        base ((enttiy, request) => entity.SomeProp == request.SomePropValue) { } 
}

This is used by the Base as such

/// Ctor
Base(Expression<Func<TEntity, TRequest, bool>> expression)
{
    _pipelineBuilder.AddFetchEntityStep (expression)
}

Where AddFetchEntityStep is a step in a pipeline

The pipeline looks like this.

Step 1 : FetchEntity Step 2 : Executing Step 3 : Validate Step 3 : Executed

Now there are two ways of retrieving an entity by Id or by another property.

For this I have a

ReadOnlyRepository
{
    TEntity GetById<TEntity>(object id) { .... } 
    TEntity GetBy<TEntity>(Expression<Func<TEntity, bool>> expression) { .... }

In the AddFetchEntityStep I do a check in order to know what Get to invoke, something like

public void AddFetchEntityStep (Expression<Func<TEntity, URequest, bool>> expression = null)
{
     if (expression == null )
     {   
         _repo.GetById<TEntity>(1)
     }  

     else 
     {
         _repo.GetBy(.....) //// The problem 
     }
}

I know they are two different signatures Expression<Func<TEntity,bool>> and Expression<Func<TEntity, TRequest, bool>>


Solution

  • You cannot simply use lambda expression to convert an expression tree to another.

    As long as the request parameter is not provided by the caller that specifies lambda expression , consider use Func<URequest,Expression<Func<TEntity,bool>>> instead of Expression<Func<TEntity, URequest, bool>>.

    And the lambda expression would look like this

    (request) => (enttiy) => entity.SomeProp == request.SomePropValue.

    Then your base class could call it to bind a 'request' object to the expression.

    Btw, generic parameter names with prefix other than T is antipattern.