Ozan Yurtsever
Ozan Yurtsever

Reputation: 1304

Passing lambda function as parameter and give its parameter in the method body

I have a method where I handle some pagination logic of a plugin;

public async Task<JsonResult> DataPagination()
{
    List<GLAccountModel> glAccounts = await HttpClientHelper.GetListHttpResponseAsync<GLAccountModel>(httpBaseAdress, "GLAccount", "GetAll");

    var (filteredResultCount, totalRecord) = DataTableHelper.ManageDataTable(glAccounts, Request, x => x.Name.Contains());

    return Json(new { data = glAccounts, draw = Request["draw"], recordsTotal = totalRecord, recordsFiltered = filteredResultCount });
}

Here, I am passing the lambda function x => x.Name.Contains() to the ManageDataTable method. Here is the implementation of ManageDataTablemethod;

public static (int, int) ManageDataTable<TModel>(List<TModel> models, HttpRequestBase request, Func<TModel, bool> lambdaExpression) where TModel : class
{               
    string search = request["search[value]"];//arama

    if (!string.IsNullOrEmpty(search))
    {
        models = models.Where(lambdaExpression).ToList();
    }

    return (filteredResultCount, totalRecord);
}

I want to be able to give the parameter of Contains() method in the body of ManageDataTable() method rather then sending it with the parameter itself. To be more clear, I want to receive the lambda function x => x.Name.Contains() from ManageDataTable(), and inside the body of ManageDataTable() I want to be able to give a parameter to the Contains() method which is a part of my lambda function. Is that possible? Thanks.

Upvotes: 0

Views: 174

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499770

There are two options I can imagine here, in terms of changing the method parameter. You could either make it a Func<string, Func<TModel, bool>> like this:

public static (int, int) ManageDataTable<TModel>(
    List<TModel> models,
    HttpRequestBase request,
    Func<string, Func<TModel, bool>> filterProvider)
    where TModel : class
{
    string search = request["search[value]"];//arama

    if (!string.IsNullOrEmpty(search))
    {
        var filter = filterProvider(search);
        models = models.Where(filter).ToList();
    }

    return (filteredResultCount, totalRecord);
}

You'd call that like this:

DataTableHelper.ManageDataTable(glAccounts, Request,
    search => model => model.Name.Contains(search));

This approach is effectively a higher-ordered method. Alternatively, you could take a Func<TModel, string, bool> like this:

public static (int, int) ManageDataTable<TModel>(
    List<TModel> models,
    HttpRequestBase request,
    Func<TModel, string, bool> filter)
    where TModel : class
{
    string search = request["search[value]"];//arama

    if (!string.IsNullOrEmpty(search))
    {
        models = models.Where(model => filter(model, search)).ToList();
    }

    return (filteredResultCount, totalRecord);
}

You'd call that like this:

DataTableHelper.ManageDataTable(glAccounts, Request,
    (model, search) => model.Name.Contains(search));

It doesn't matter very much which of those you use - but it's worth making sure you understand both of them.

Upvotes: 6

Related Questions