如何在对异步方法的调用上追加对扩展方法的调用

时间:2018-07-12 16:53:45

标签: c# asp.net-core

我有一个自定义扩展方法“ ToSelectList”,我目前正像这样使用它:

        var myList = await _myService.GetItems();
        var mySelectList = myList.ToSelectList(nameof(MyEntity.Id));

那很好,效果很好,但是,我尝试将其作为一行:

        var myList = await _myService.GetItems().ToSelectList(nameof(MyEntity.Id));

但是我得到了

'Task<List<MyEntity>>' does not contain a definition for 'ToSelectList'
and no extension method 'ToSelectList' accepting a first argument of type
'Task<List<MyEntity>>' could be found (are you missing a using directive 
or an assembly reference?)

我的ToSelectList方法如下:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace MyProject.Extensions
{
    public static class ListExtensions
    {
        public static List<SelectListItem> ToSelectList<T>(this List<T> list, string id, string text = "Name")
        {
            var selectListItems = new List<SelectListItem>();

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

            return selectListItems;
        }
    }

我尝试将方法签名更改为public async static Task<List<SelectListItem>>,但并不高兴。

3 个答案:

答案 0 :(得分:1)

问题在于await适用于整行,因此您要么需要将其用括号括起来:

var myList = (await _myService.GetItems())
    .ToSelectList(nameof(MyEntity.Id));

或将其分为两行:

var items = await _myService.GetItems();
var myList = items.ToSelectList(nameof(MyEntity.Id));

答案 1 :(得分:1)

虽然@DavidGanswer是正确的,但我建议您简化逻辑。如果您使用内置的Tuple<T1, T2>,则不需要任何反射代码:

// let's assume this is in your service class
// you most likely want a better name
public Task<List<Tuple<int, string>>> GetItemsAsEnumAsync()
{
    return _context.SomeTable
        .Select(x => Tuple.Create(x.Id, x.Name))
        .ToListAsync();
}

您的ToSelectList就是:

public static List<SelectListItem> ToSelectList(this List<Tuple<int, string>> list)
{
    return list
        .Select(x => new SelectListItem
        {
            Value = x.Item1.ToString(),
            Text = x.Item2
        })
        .ToList();
}

这假定您的服务与ASP.NET Core应用程序不在同一个项目中,因此无法返回List<SelectListItem>本身。如果发现有用,可以使用ToSelectList使ToSelectList<T1, T2>(this List<KeyValuePair<T1, T2>> list)更通用。

答案 2 :(得分:-5)

您可以选择:

var myList = _myService.GetItems().Result.ToSelectList(nameof(MyEntity.Id));

但这只会阻塞线程,您将执行非异步代码

或将_myService.GetItems()的结果更改为List<SelectListItem>

无论如何,如果您立即需要结果,那么异步的意义是什么?