Search code examples
linq-to-entitiesentity-framework-4.1expression-treespredicatebuilder

Shorter Way To Write Expression Trees with Predicate Builder


Is there an easier way to write the expression trees with Predicate Builder. It just seems like a lot of code that can be condensed.

Expression<Func<EventGymCourt, object>> gymCourt = q => q.GymCourt;
Expression<Func<EventGymCourt, object>> gym = q => q.GymCourt.Gym;
Expression<Func<EventGymCourt, object>> address = q => q.GymCourt.Gym.Address;

_eventGymCourtRepository.GetWithStart(page, pageSize, new[] { gymCourt, gym, address }....

Solution

  • Well, I doubt that the types of the GymCourt, Gym and Address members are all object, so it's going to be difficult to get type-inference to work in your favour.

    One way would be to use an array-initializer:

    Expression<Func<EventGymCourt, object>>[] exprs 
          = { q => q.GymCourt, q => q.GymCourt.Gym, q => q.GymCourt.Gym.Address };
    
    _eventGymCourtRepository.GetWithStart(page, pageSize, exprs);
    

    If you really need each expression in a separate variable, you can use a using-alias to shorten the variable type-declaration.

    // At the top of your file....
    using CourtObjectExpr = 
      System.Linq.Expressions.Expression<System.Func<MyNameSpace.EventGymCourt, object>>;
    
    ...
    
    CourtObjectExpr gymCourt = q => q.GymCourt;
    CourtObjectExpr gym = q => q.GymCourt.Gym;
    CourtObjectExpr address = q => q.GymCourt.Gym.Address;
    

    By the way, you appear to be searching for the Linq.Expr method from LINQKit (the library that contains PredicateBuilder). This uses the compiler's type-inference features to condense the conversion of a lambda to an expression-tree in typical scenarios. I don't think this is all that useful in your example since you require the expression's return-type to be object rather than the property-type.

    But assuming you want to create expressions with the property-type as the expression's return-type, you could have done (quite succinctly):

    // Not directly applicable to your scenario (you can add a cast).
    var gymCourt = Linq.Expr((EventGymCourt q) => q.GymCourt);
    var gym =  Linq.Expr((EventGymCourt q) => q.GymCourt.Gym);
    var address = Linq.Expr((EventGymCourt q) => q.GymCourt.Gym.Address);
    

    This lets compiler type-inference work in your favour; the source-code for the method is as simple as:

    public static Expression<Func<T, TResult>> Expr<T, TResult>
               (Expression<Func<T, TResult>> expr)
    {
        return expr;
    }
    

    While that's not a direct fit for your situation, it's good to have in your toolkit.