every Parameter object property that is not null, to be added to expression predicate as a condition

You don't need to use Expressions to build something dynamically here. You can do something like this:

_unitOfWork.Accounts.Where(a =>
    (params.CustomerId == null || a.CustomerId == params.CustomerId) &&
    (params.AccountId == null || a.AccountId == params.AccountId) &&
    (params.ProductId == null || a.ProductId == params.ProductId) &&
    (params.CurrencyId == null || a.CurrencyId == params.CurrencyId)
);

This is how I've done queries before for a search form with multiple optional search parameters.


I'm currently working a lot with Expressions so I think I can help you.

I just built a custom code for you.

The code accepts that you add Properties to your filtered class (Account) without having to change the filter building code.

The code filters string Properties and use it to create the Predicate.

public Func<Account, bool> GetPredicate(Parameters parameters)
{
    var stringProperties = typeof(Parameters)
    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
    .Where(x => x.PropertyType == typeof(string));

    var parameterExpression = Expression.Parameter(typeof(Account));

    var notNullPropertyNameToValue = new Dictionary<string, string>();

    BinaryExpression conditionExpression = null;

    foreach (var stringProperty in stringProperties)
    {
        var propertyValue = (string)stringProperty.GetValue(parameters);
        if (propertyValue != null)
        {
            var propertyAccessExpression = Expression.PropertyOrField(parameterExpression, stringProperty.Name);
            var propertyValueExpression = Expression.Constant(propertyValue, typeof(string));
            var propertyTestExpression = Expression.Equal(propertyAccessExpression, propertyValueExpression);

            if (conditionExpression == null)
            {
                conditionExpression = propertyTestExpression;
            }
            else
            {
                conditionExpression = Expression.And(conditionExpression, propertyTestExpression);
            }
        }
    }

    //Just return a function that includes all members if no parameter is defined.
    if (conditionExpression == null)
    {
        return (x) => true;
    }

    var lambdaExpression = Expression.Lambda<Func<Account, bool>>(conditionExpression, parameterExpression);
    return lambdaExpression.Compile();
}

It returns a typed predicate that you can use in Linq for example.

See this example :

void Main()
{
    var customers = new List<Account>()
    {
        new Account()
        {
            CustomerId = "1",
        },
        new Account()
        {
            CustomerId = "2",
        }
    };
    var predicate = GetPredicate(new Parameters() { CustomerId = "1" });

    customers.Where(predicate);
}

If any help is needed, feel free to ask !