Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# refactoring lambda expressions

I have several Expression<Func<User,bool>> expressions that shares properties. For example,

Expression<Func<User, bool>> e1 = 
  (User u) => u.IsActive && u.Group != "PROCESS" && u.Name != null;
Expression<Func<User, bool>> e2 = 
  (User u) => u.IsActive && u.Group != "PROCESS" && u.Name != "A";
Expression<Func<User, bool>> e3 = 
  (User u) => u.IsActive && u.Group != "PROCESS" && u.Name != "B";

Is there an easy way to put the u.IsActive && u.Group != "PROCESS" in a variable and use it in e1, e2 and e3? Edited : And I still want the same tree.

Seems I can do it by building the expression with Expression.Lambda<Func<User, bool>>(BinaryExpression.AndAlso( etc... But rather than simplifying my code it made it more difficult to read.

like image 412
Toto Avatar asked Sep 17 '09 13:09

Toto


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.


2 Answers

I believe there's no cleaner way to do that for your case. You can use BinaryExpression as you mentioned. You can encapsulate the BinaryExpression and Expression.Lambda calls into a method and call that instead (like PredicateBuilder.And) but none of those are as clean as the current syntax IMO.

like image 195
mmx Avatar answered Sep 17 '22 12:09

mmx


Problem with lambda expressions is that they are immutable and you can't easily replace parameters of lambda. My original idea was to do something like this (unfortunately, this won't work out):

public static class ExpressionExtesions
{
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> baseCondition, Expression<Func<T, bool>> additionalCondition)
    {
        var and = Expression.AndAlso(baseCondition.Body, additionalCondition.Body);
        return Expression.Lambda<Func<T, bool>>(and, baseCondition.Parameters);  // additionalCondition.Body still uses its own parameters so this fails on Compile()
    }
}

and use in code:

Expression<Func<User, bool>> e = usr => usr.IsActive && usr.Group != "PROCESS";

var e1 = e.And(u => u.Name != null);
var e2 = e.And(u => u.Name != "A");
var e3 = e.And(u => u.Name != "B");

Possible solution

You can try to use one of the project aiming on implementing expression builders. I haven't used any of them but google gives plenty of links, for example:

  • Metalinq
  • LINQ: BUILDING AN IQUERYABLE PROVIDER - PART II
  • Dealing with Linq’s Immutable Expression Trees

Another approach

If you are using these expressions in LINQ to filter values, you can user different approach (don't combine expressions but combine filters):

var activeUsers = allUsers.Where(usr => usr.IsActive && usr.Group != "PROCESS");

var usersAll = activeUsers.Where(u => u.Name != null);
var usersNotA = activeUsers.Where(u => u.Name != "A");
var usersNotB = activeUsers.Where(u => u.Name != "B");
like image 33
Konstantin Spirin Avatar answered Sep 21 '22 12:09

Konstantin Spirin