首页 文章

列表结果的开放原则

提问于
浏览
0

我正在练习如何用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列表 .

这是显示 Cannot convert expression type 'System.Collections.Generic.List<System.Linq.IQueryable<FoodDto>>' to return type 'System.Collections.Generic.IEnumerable<FoodDto>' 的红色波浪线的示例结果

我希望有人可以帮助我 .

2 回答

  • 1

    或者,您可以在 IQueryable<FoodDto 上使用 async 检查下面的重构代码 .

    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));
    }
    ...
    

    另外,不要忘记在中间件或启动类上注册接口和类 .

    希望这也有助于他人 .

  • 1

    我总是想知道为什么提问者提供一些代码并说代码不起作用,没有给出确切的要求 .

    在我看来,你想为你的类 SelectTypeOFoodService 添加一个异步函数,它将两个参数作为输入: string rulestring query .

    输出应该是 this.selectInfos 中具有 this.selectInfos.Rule(rule) 的真实返回值的所有项目的 ReturnSearchResult(query)

    注意:我冒昧地将您的集合的标识符复数化,因为这样可以轻松阅读答案 .

    可能是你简化了你的要求,但对我来说,在我看来你不需要异步功能 .

    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 . 如果您的呼叫者在调用您的 SelectFood 之后会使用 FirstOrDefault 将您的所有千种食物转换为列表然后仅使用第一种食物将是浪费 .

    如果您确实需要调用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,它只会降低你的代码效率 .

    有时,您的类没有什么可以等待,但您确实需要创建异步函数,例如实现返回Task的接口,或者在单元测试中模拟功能以测试使用async-await的功能 .

    在这种情况下,让异步函数调用sync函数并使用 Task.FromResult 来组成返回值

    Task<List<FoodDto>> SelectFoodAsync((string rule, string query)
    {
        List<FoodDto> selectedFoods = this.SelectFoods(rule, query);
        return Task.FromResult(selectedFoods);
    }
    

相关问题