首页 > 解决方案 > 从通用数据类型填充 SelectListItem

问题描述

我有以下代码,它从包含 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;
}));

标签: c#asp.netlinqasp.net-coreselectlistitem

解决方案


您可以为通用列表对象创建自定义扩展,然后使用反射检索您想要映射到 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; }
}

推荐阅读