Как объединить эти 2 аналогичных метода в один? - PullRequest
5 голосов
/ 06 мая 2009

Я видел несколько примеров использования 'T', чтобы сделать метод многократно используемым для универсальных коллекций различных классов, но я никогда не понимал его.

Интересно, можно ли было бы объединить 2 приведенных ниже метода в один и каковы были бы недостатки этого (с точки зрения производительности).

Кто-нибудь?

        [NonAction]
        public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, string defaultOption)
        {
            var items = departments.Select(d => new SelectListItem() { Text = d.Code + " - " + d.Description, Value = d.Id.ToString() }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }

        [NonAction]
        public List<SelectListItem> ToSelectList(IEnumerable<Function> functions, string defaultOption)
        {
            var items = functions.Select(f => new SelectListItem() { Text = f.Description, Value = f.Id.ToString() }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }

РЕШЕНИЕ

Решение, которое я использовал:

использование

var departmentItems = departments.ToSelectList(d => d.Code + " - " + d.Description, d => d.Id.ToString(), " - ");
var functionItems = customerFunctions.ToSelectList(f => f.Description, f => f.Id.ToString(), " - ");

с

 public static class MCVExtentions
    {
        public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption)
        {
            var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList();
            items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
            return items;
        }
    }

Ответы [ 3 ]

8 голосов
/ 06 мая 2009

Старый способ - создать общий интерфейс как для отдела, так и для функции:

interface A
{
int ID{get;}
string Description{get;}
}

Вы вводите описание в отдел для возврата d.Code + " - " + d.Description. и напишите функцию для использования этого интерфейса вместо конкретных классов:

[NonAction]
    public List<SelectListItem> ToSelectList(IEnumerable<A> as, string defaultOption)
    {
        var items = as.Select(a => new SelectListItem() { Text = a.Description, Value = a.Id.ToString() }).ToList();
        items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
        return items;
    }

РЕДАКТИРОВАТЬ: Что касается использования дженериков, это не очень поможет в этом случае, потому что

  • объекты, которые вы передаете, должны реализовать Id и Description
  • вы не возвращаете эти объекты, поэтому в этом отношении вам не нужно заботиться о безопасности типов дженериков
7 голосов
/ 06 мая 2009

Без реализации общего интерфейса, подобного предложенному @Grzenio, вы можете использовать универсальный метод, подобный этому:

    public List<SelectListItem> ToSelectList<T>(IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption)
    {
        var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList();
        items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
        return items;
    }

    // use like

    t.ToSelectList(departments, d => d.Code + " - " + d.Description, d => d.Id.ToString(), "default");
    t.ToSelectList(functions, f => f.Description, f => f.Id.ToString(), "default");
4 голосов
/ 06 мая 2009

На самом деле вы можете сделать это с помощью комбинации обобщенных функций и функций, что-то вроде этого (непроверенный может даже не скомпилироваться).

[NonAction]
public List<SelectListItem> ToSelectList<T>(IEnumerable<T> en, 
                                            Function<string, T> text, 
                                            Function<string, T> value, 
                                            string defaultOption)
{
    var items = en.Select(x => new SelectListItem() { Text = text(x) , Value = value(x) }).ToList();
    items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" });
    return items;
}

Затем вы можете отправлять на него соответствующие лямбда-функции (или вызывать напрямую).

[NonAction]
public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, 
                                         string defaultOption)
{
    return ToSelectList<Department>(departments, d =>  d.Code + '-' + d.Description, d => d.Id.ToString(), defaultOption);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...