Открыто-закрытый принцип для результата списка - PullRequest
0 голосов
/ 10 декабря 2018

Я практикую, как создать открытый-закрытый принцип с C #, чтобы вернуть список информации.но проблема в том, что я получаю ошибку в своем основном классе обслуживания.

Вот мои примеры кодов:

У меня есть этот интерфейс:

public interface ISelectInfo{
    bool Rule(string rule);
    IQueryable<FoodDto> ReturnSearchResult(string query);
}

У меня естьэтот класс, который реализует этот интерфейс.

public class Fruit : ISelectInfo {
    public bool Rule(string rule){ 
        return "fruit".Equals(rule); 
    }
    public IQueryable<FoodDto> ReturnSearchResult(string query){
        // returns a list of FoodDto
    }
}

И у меня есть этот основной класс обслуживания

public class SelectTypeOFoodService {
    private readonly IList<ISelectInfo> selectInfo;
    public SelectTypeOfFruitService (IList<ISelectInfo> selectInfo){
        this.selectInfo = selectInfo;
    }

    public async IEnumerable<FoodDto> SelectFood(string rule, string query){
        return await selectInfo.ToList().Where(x=>x.Rule(rule)).Select(x=>x.ReturnSearchResult(query)).AsQueryable().TolistAsync();
    }
}

Я получаю сообщение об ошибке и красная линия закорочения на моем return await selectInfo.ToList()...

То, что я пытаюсь добиться, чтобы вернуть список FoodDto, основанный на принципе Open-closed.

Вот пример результата красной красной линии, которая показывает Cannot convert expression type 'System.Collections.Generic.List<System.Linq.IQueryable<FoodDto>>' to return type 'System.Collections.Generic.IEnumerable<FoodDto>'

Надеюсь, кто-нибудь сможет мне помочь.

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Мне всегда интересно, почему спрашивающие дают некоторый код и говорят, что код не работает, без точного требования.

Мне кажется, что вы хотите добавить асинхронную функцию в свой класс SelectTypeOFoodService который принимает два параметра в качестве входных данных: string rule и string query.

Выходными данными должны быть ReturnSearchResult(query) всех элементов в this.selectInfos, которые имеют истинное возвращаемое значение для this.selectInfos.Rule(rule)

Примечание: я позволил себе множить идентификаторы ваших коллекций, поскольку это облегчило бы чтение ответа.

Возможно, вы упростили свои требования, но мне кажется, что вы не захотитеДля этого не нужна асинхронная функция.

IQueryable<FoodDto> QueryFood(string rule, string query)
{
    return this.selectInfos
        .Where(selectInfo => selectInfo.Rule(rule))
        .Select(selectInfo => selectInfo.ReturnSearchResult(query);
}

IEnumerable<FootDto> SelectFood(string rule, string query)
{
     return this.QueryFood(rule, query).AsEnumerable();
}

Я выбрал использование AsEnumerable вместо ToList, потому что, очевидно, вы хотите вернуть IEnumerable.Если ваш вызывающий абонент будет использовать FirstOrDefault после вызова вашего SelectFood, было бы бесполезно конвертировать все ваши тысячи продуктов в список, а затем использовать только первый.

Если вам действительно нужно вызвать ToListНапример, поскольку вы удаляете свой запрашиваемый объект, рассмотрите возможность возврата List вместо IEnumerable.Это не позволит пользователям вызывать лишние ToList, вызывая повторное указание списка ваших элементов.

List<FoodDto> SelectFood(string rule, string query)
{
     return this.QueryFood(rule, query).ToList()
}

Теперь может иметь смысл создать асинхронную версию, поскольку ToList - это функция, которая будетна самом деле выполнить запрос, и если запрос должен выполняться ожидаемым процессом (например, запрос к базе данных, извлечение данных из Интернета, чтение файла), то может быть целесообразно создать асинхронную функцию:

Task<List<FoodDto>> SelectFoodAsync((string rule, string query)
{
     return this.QueryFood(rule, query).ToListAsync();
}

Еще раз: если нечего ждать, не вводите async-await в классе, это только сделает ваш код менее эффективным.

Иногда вашим классам нечего ждать,но вам нужно создать асинхронную функцию, например, для реализации интерфейса, возвращающего задачу, или для проверки функциональности в модульном тесте, чтобы протестировать функциональность, использующую async-await.

В этом случае позвольтеасинхронная функция вызывает функцию синхронизации и использует Task.FromResult для составления возвращаемого значения

Task<List<FoodDto>> SelectFoodAsync((string rule, string query)
{
    List<FoodDto> selectedFoods = this.SelectFoods(rule, query);
    return Task.FromResult(selectedFoods);
}
0 голосов
/ 10 декабря 2018

В качестве альтернативы, вы можете использовать async на вашем IQueryable<FoodDto Проверьте мои коды рефакторинга ниже.

public class Fruit : ISelectInfo {
    public bool Rule(string rule){ 
        return "fruit".Equals(rule); 
    }
    public async Task<IEnumerable<FoodDto>> ReturnSearchResult(string query){
        // returns a list of FoodDto
    }
}

На вашем обслуживании,

... 
public async Task<IEnumerable<FoodDto>> SelectFood(string rule, string query){
    return await selectInfo.FirstOrDefault(x=>x.Rule(rule)).Select(x=>x.ReturnSearchResult(query));
}
...

Кроме того, нене забудьте зарегистрировать свои интерфейсы и класс на промежуточном программном обеспечении или классе запуска.

Надеюсь, это поможет и другим.

...