重构LINQ方法以引入Lamba函数作为参数

时间:2019-09-16 07:54:48

标签: c# linq lambda refactoring expression

我有当前代码,它使用LINQ从ID列表中选择经过验证的ID:

var ids = idList
            .Select(page => page.PageId?? -1)
            .Where(id => id > -1)
            .Distinct()
            .ToArray();

在我的应用程序中,我经常使用此代码片段,我想知道是否可以将这段代码包装在另一个函数中,并通过两个lambda表达式作为参数来缩短它。

类似的东西:

int[] pageIds = getIdsOfPages(page => page.Id ?? -1, id => id > -1);

我可以实施此方法吗?

我看过lambda表达式和函数,但是到目前为止我还没有运气。 Expression<Func<Object, Bool>>Func<Object, Bool>

P.s第二个参数id> -1。那将是一个常量..只有第一个参数会改变。

谢谢。

修改

这是我当前的实现: 调用方式:

public int[] getPageIds(List<PageObject> pageHeadersList){

    IQueryable<DataModel.PageHeader> list = pageHeadersList.AsEnumerable().AsQueryable();

    int[] pageIds = list.GetIds(x => x.PageId ?? -1);

    return pageIds;
}



public static IQueryable<T> ExecuteWhereClause<T>(IQueryable<T> inputQuery, string paramName, object typedValue)
{
        ParameterExpression parameter = Expression.Parameter(typeof(T));
        var condition =
                Expression.Lambda<Func<T, bool>>(
                    Expression.GreaterThan(
                        Expression.Property(parameter, paramName),
                        Expression.Constant(typedValue)
                    ),
                    parameter
                );

        return inputQuery.Where(condition);
}


public static int[] GetIds<TSource, TKey>(this IQueryable<TSource> list, Func<TSource, TKey> keySelector)
{

        var newList = list.Select(keySelector)
             .AsQueryable();

        var newListAfterWhere = ExecuteWhereClause(newList , "Id", -1);

        return newListAfterWhere .Cast<int>().ToArray();
 }

2 个答案:

答案 0 :(得分:1)

实际上SelectWhere告诉您它们需要哪种输入函数。答案已经在您的问题中。

对于Where,您需要

Expression<Func<int, bool>> filter

Select

Expression<Func<YourType, int>> selector

这是一个带有自定义类的示例:

public static class Extensions
{
    public static int[] getIdsOfPages<TSource>(this IQueryable<TSource> list, Expression<Func<TSource, int>> select, Expression<Func<int, bool>> filter)
    {
        return list
            .Select(select)
            .Where(filter)
            .Distinct()
            .ToArray();
    }
}

您会这样称呼它:

int[] pageIds = idList.AsQueryable().getIdsOfPages(page => page.PageId ?? -1, id => id > -1);


public static List<MyClass> idList = new List<MyClass>();
public class MyClass
{
    public int? PageId { get; set; }
}

尽管您希望我先提高效率,但请先过滤然后选择。您将对选择器功能进行一些修改:

public static int[] getIdsOfPagesFilterFirst<TSource>(
                   this IQueryable<TSource> list, 
                   Expression<Func<TSource, int>> select, 
                   Expression<Func<TSource, bool>> filter)
{
    return list.Where(filter).Select(select).Distinct().ToArray();
}

并这样称呼它:

int[] pageIds = idList.AsQueryable().getIdsOfPagesFilterFirst(page => page.PageId.Value , page => page.PageId.HasValue);

答案 1 :(得分:0)

这是我之前创建的,它允许Where,OrderBy和Select其中T = YourClass

public IQueryable<T> Get(
    Expression<Func<T, int>> select,
    Expression<Func<T, bool>> where,
    Func<IQueryable<T>, IOrderedQueryable<T>> orderBy)
{
    var databaseSet = this.Context.Set<T>();
    var query = (IQueryable<T>) databaseSet;
    if (filter != null)
    {
        query = query.Where(where);
    }

    if (orderBy != null)
    {
        query = orderBy(query);
    }

    if (select != null)
    {
         query = query.Select(select);
    }

    return query;
}