Заполните SelectListItem из универсального типа данных - PullRequest
0 голосов
/ 01 мая 2018

У меня есть следующий код, который возвращает результаты из таблицы базы данных, состоящей из поля Id и поля Name, и передает ее в список SelectListItems (это заполняет раскрывающийся список в моем представлении).

var locationTypes = await APIHelper.GetAsync<List<LocationType>>(url);

var items = new List<SelectListItem>();

items.AddRange(locationTypes.Select(locationType =>
{
    var item = new SelectListItem();
    item.Value = locationType.LocationTypeId.ToString();
    item.Text = locationType.Name;
    return item;
}));

Я повторяю это во всем приложении, заменяя LocationType другими вещами. Item.Value всегда получает свойство Id возвращаемых данных (поле Id всегда имеет формат {TableName} + "Id"), а item.Text всегда получает свойство ".Name".

Как я могу сделать это универсальным? Я пытаюсь добиться чего-то подобного, хотя это синтаксически неверно и может быть неправильным подходом:

var myGenericObjects = await APIHelper.GetAsync<List<T>>(url)

var items = new List<SelectListItem>();

items.AddRange(myGenericObjects .Select(myGenericObjects =>
{
    var item = new SelectListItem();
    item.Value = myGenericObject.Field[0].ToString();
    item.Text = myGenericObject.Name;
    return item;
}));

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Некоторые подготовительные работы

Если вы можете изменить имена столбцов таблицы, используйте соглашение. Например, всегда называйте столбец «Значение» «X», а столбец «Текст» - «Y» (дайте им более подходящие имена). Затем заставьте все классы для этих таблиц реализовать интерфейс, подобный следующему:

public interface ICustomLookup
{
    string X { get; set; }
    string Y { get; set; }
}

public class SomeClass : ICustomLookup
{
    public string X { get; set; }
    public string Y { get; set; }
}

Тогда метод расширения примерно такой:

public static class EnumerableExtension
{
    public static SelectList ToSelectList(this IEnumerable<ICustomLookup> items)
    {
        return new SelectList(items.Select(thisItem => new SelectListItem
        {
            Text = thisItem.X,
            Value = thisItem.Y
        }));
    }
}

Usage

var items = new List<SomeClass>
{
    new SomeClass { X = "XOne", Y = "YOne" },
    new SomeClass { X = "XTwo", Y = "YTwo" }
};
SelectList selectList = items.ToSelectList();
0 голосов
/ 02 мая 2018

Вы можете создать собственное расширение для универсального объекта списка, а затем с помощью отражения получить значения, которые вы хотите отобразить, в поля SelectListItem.Text и Name. Примечание. Я использую «nameof», чтобы избежать путаницы или магических строковых представлений свойств, которые я пытаюсь отобразить.

Я определил значение по умолчанию «Имя» для параметра namePropertyName. По вашему описанию это звучало так, как обычно, в большинстве ваших DTO есть свойство «Имя». Если это не так, просто удалите значение по умолчанию, которое определено.

Существуют дополнительные проверки, которые могут быть выполнены для этого расширения, чтобы предотвратить исключения NullReference и ArgumentExceptions, но для простоты примера были опущены. Пример. Обеспечение значения в параметрах idPropertyName и namePropertyName и обеспечение наличия этих имен свойств в предоставленном универсальном объекте до преобразования.

public static class ListExtensions
{
    public static List<SelectListItem> ToSelectList<T>(this List<T> list, string idPropertyName, string namePropertyName = "Name")
        where T : class, new()
    {
        List<SelectListItem> selectListItems = new List<SelectListItem>();

        list.ForEach(item =>
        {
            selectListItems.Add(new SelectListItem
            {
                Text = item.GetType().GetProperty(namePropertyName).GetValue(item).ToString(),
                Value = item.GetType().GetProperty(idPropertyName).GetValue(item).ToString()
            });
        });

        return selectListItems;
    }
}

Пример использования:

var testList = new List<TestDto>
{
    new TestDto { Name = "Test0", TestId = 0 },
    new TestDto { Name = "Test1", TestId = 1 },
    new TestDto { Name = "Test2", TestId = 2 },
    new TestDto { Name = "Test3", TestId = 3 },
    new TestDto { Name = "Test4", TestId = 4 },
};

var selectList = testList.ToSelectList(nameof(TestDto.TestId), nameof(TestDto.Name));

Вот класс TestDto для справки:

public class TestDto
{
    public int TestId { get; set; }
    public string Name { get; set; }
}
...