每个不为 null 的参数对象 属性,作为条件添加到表达式谓词

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

我正在寻找一种基于方法参数动态构建表达式的方法。

这是我的服务方法的代码片段,我想在其中构建谓词表达式。

    public async Task<Account> GetCustomerAccountsAsync(Parameters params)
    {
        var items = await _unitOfWork.Accounts.GetWhereAsync(a => a.CustomerId == params.CustomerId && ... );
        ...
    }

GetWhereAsync 是通用存储库中的一种方法,如下所示:

    public async Task<IEnumerable<TEntity>> GetWhereAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await Context.Set<TEntity>().Where(predicate).ToListAsync();
    }

参数 class:

    public class Parameters
    {
        public string CustomerId { get; set; }
        public string AccountId { get; set; }
        public string ProductId { get; set; }
        public string CurrencyId { get; set; }
    }

我想实现的是,每个 Parameter 对象 属性 不是 null, 作为条件添加到表达式谓词。

例如,如果 CustomerIdAccountId 有一些值,我想动态构建谓词表达式 将具有与以下谓词相同的功能:

    var items = await _unitOfWork.Accounts.GetWhereAsync(a => a.CustomerId == params.CustomerId && a.AccountId == params.AccountId);

感谢任何帮助。

您不需要使用表达式在此处动态构建某些内容。你可以这样做:

_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)
);

这就是我之前对具有多个可选搜索参数的搜索表单进行查询的方式。

我目前经常使用表达式,所以我想我可以帮助你。

我刚刚为您构建了自定义代码。

该代码接受您将属性添加到过滤后的 class(帐户),而无需更改过滤器构建代码。

代码过滤字符串属性并使用它来创建谓词。

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();
}

它 returns 一个类型化的谓词,您可以在 Linq 中使用,例如。

看这个例子:

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);
}

如果需要任何帮助,请随时提出!