【问题标题】:Returns Generic type Database result set in C#返回 C# 中的通用类型数据库结果集
【发布时间】:2017-02-27 08:09:34
【问题描述】:

我编写了一个具体的类来公开数据库结果集,其中包括 T 型列表项和总行数。经过一番阅读(依赖倒置原理,接口隔离原理),我发现它应该暴露为接口而不是具体类。

这是我的代码,编写此类以公开为IDbResultSet 而不是公开为DbResultSet 的最佳方法是什么。

public class DbResultSet<T>
{
    public List<T> Items { get; private set; }
    public int TotalRowCount { get; private set; }

    public DbResultSet(List<T> items, int totalRowCount)
    {
        this.Items = items;
        this.TotalRowCount = totalRowCount;
    }
}

用法:

DbResultSet<Category> GetCategory(int categoryId);

【问题讨论】:

    标签: c# oop interface generic-list


    【解决方案1】:

    你无能为力。这只是关于设计界面:

    public interface IDbResultSet<T, TCollection>
           where TCollection : ICollection<T>
    {
         TCollection Items { get; }
         int TotalRowCount { get; }
    }
    

    正如你在上面看到的,整个接口没有定义Items集合类型:它可以是任何实现ICollection&lt;T&gt;的集合。

    现在你可以按如下方式实现它:

    public class DbResultSet<T, TCollection> : IDbResultSet<T, TCollection>
           where TCollection : ICollection<T> 
    {
        public TCollection  Items { get; private set; }
        public int TotalRowCount { get; private set; }
    
        public DbResultSet(TCollection items, int totalRowCount)
        {
            // Note that qualifying with "this" is redundant here
            // so I've removed it
            Items = items;
            TotalRowCount = totalRowCount;
        }
    }
    

    顺便说一句,我建议你将接口和类名从ResultSet 更改为Result 按原样,因为 set 是一个集合没有顺序但集合项是唯一的类型:

    public interface IDbResult<T, TCollection>
           where TCollection : ICollection<T>
    {
         TCollection Items { get; }
         int TotalRowCount { get; }
    }
    
    public class DbResult<T, TCollection> : IDbResultSet<T, TCollection>
           where TCollection : ICollection<T> 
    {
        public TCollection  Items { get; private set; }
        public int TotalRowCount { get; private set; }
    
        public DbResult(TCollection items, int totalRowCount)
        {
            // Note that qualifying with "this" is redundant here
            // so I've removed it
            Items = items;
            TotalRowCount = totalRowCount;
        }
    }
    

    因此,您可以将类型化为接口类型的结果公开:

    IDbResult<Category, IList<Category>> GetCategories();
    

    一些建议

    我看到您甚至想对单个结果使用这种方法:

     DbResultSet<Category> GetCategory(int categoryId);
    

    我的建议是你应该将你的结果分成两个家庭

    • 单个结果。
    • 多个结果。

    所以我最终会得到这些接口:

    public interface IMultipleDbResult<T, TCollection>
           where TCollection : ICollection<T>
    {
         TCollection Items { get; }
         int TotalRowCount { get; }
    }
    
    public interface ISingleDbResult<T>
    {
          T Item { get; }
    }
    

    我建议您这样做是因为奇怪的是您知道自己正在通过Id 获得一个类别,并且您可能需要从列表中获取它:

    IDbResult<Category, IList<Category>> result = GetCategoryById(389);
    Category category = result.Items[0]; // ??????
    
    // vs.
    
    ISingleDbResult<Category> result = GetCategoryById(389);
    Category category = result.Item; // Isn't it more elegant?
    

    顺便说一句,我了解您的实际解决方案涉及在两种结果类型上实现更多属性。例如收集数据库查询错误信息或其他有用的数据。

    另一方面,我猜你正在实现像TotalRowCount 这样的属性,因为你正在对结果进行分页。例如,可能有 300 个类别,但 Items 属性包含第一页中的 10 个项目。否则,您的推理有一些缺陷,因为 ICollection&lt;T&gt; 的所有实现都已经拥有 Count 属性。

    最后,也许对我在网上发布的一些设计模式感兴趣。见Accmulated Result design pattern

    【讨论】:

    • 你成功了。您已经回答了我心中的所有问题,例如:SingleResult 概念。干杯!
    • @Aruna 没问题!不客气。看看我建议你的设计模式,这可能是你的决定:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2013-07-02
    相关资源
    最近更新 更多