Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a generic select list generating method of type T

I was wondering how I might be able to create a re-usable method that creates select lists based on method arguments? I was thinking something like below:

public IEnumerable<SelectListItem> CreateSelectList(IList<T> entities, T value, T text)
{

   return  entities
           .Select(x => new SelectListItem
                           {
                               Value = x.value.ToString(),
                               Text = x.text.ToString()
                           });
}

I think I have it a bit backwards though. I'm unsure how to call a method like this, when I call it with an IList of Category for the first argument the compiler complains that it cannot assign type Category to type T? Also, how would I insert the method arguments into the lambda? Any help appreciated!

Code I'm trying to use to call it (which is wrong, but you get the idea)

viewModel.Categories = _formServices.CreateSelectList(categories, Id, Name);

Code I'm trying to make more generic and reusable:

viewModel.Categories = categories
                      .Select(x => new SelectListItem
                     {
                         Value = x.Id.ToString(),
                         Text = x.Name
                      });

Edit For Answer

Credit goes to @Pavel Backshy for working answer. I wanted to edit in an extension I made to his answer in case it helps anybody! The extension just adds a .Where clause into the mix:

    public IEnumerable<SelectListItem> CreateSelectListWhere<T>(IList<T> entities, Func<T, bool> whereClause, Func<T, object> funcToGetValue, Func<T, object> funcToGetText)
    {
        return entities
               .Where(whereClause)
               .Select(x => new SelectListItem
                {
                    Value = funcToGetValue(x).ToString(),
                    Text = funcToGetText(x).ToString()
                });
    }
like image 760
Kiada Avatar asked Jan 16 '23 19:01

Kiada


1 Answers

You can define this using Reflection to take property value by name, but I think more elegant and flexible to use Func. Change your method to:

public IEnumerable<SelectListItem> CreateSelectList<T>(IList<T> entities, Func<T, object> funcToGetValue, Func<T, object> funcToGetText)
{
    return entities
            .Select(x => new SelectListItem
            {
                Value = funcToGetValue(x).ToString(),
                Text = funcToGetText(x).ToString()
            });
}

And then you can use it by this way:

viewModel.Categories = _formServices.CreateSelectList(categories, x => x.Id, x => x.Name);
like image 85
Pavel Bakshy Avatar answered Jan 18 '23 10:01

Pavel Bakshy