【问题标题】:Is there anything wrong with having a few private methods exposing IQueryable<T> and all public methods exposing IEnumerable<T>?有一些公开 IQueryable<T> 的私有方法和公开 IEnumerable<T> 的所有公共方法有什么问题吗?
【发布时间】:2011-02-23 21:35:32
【问题描述】:

我想知道是否有更好的方法来解决这个问题。目标是重用代码。

假设我有一个 Linq-To-SQL 数据上下文,并且我编写了一个“存储库样式”类,它封装了许多我需要的方法并公开了 IQueryables。 (到目前为止,没问题)。

现在,我正在构建一个位于此存储库之上的服务层,许多服务方法将是 11 与存储库方法,但有些不会。我认为代码示例比文字更能说明这一点。

public class ServiceLayer 
{
    MyClassDataContext context;
    IMyRepository rpo;

    public ServiceLayer(MyClassDataContext ctx) 
    { 
        context = ctx; 
        rpo = new MyRepository(context);   
    }

    private IQueryable<MyClass> ReadAllMyClass()
    {
        // pretend there is some complex business logic here
        // and maybe some filtering of the current users access to "all"
        // that I don't want to repeat in all of the public methods that access
        // MyClass objects.
        return rpo.ReadAllMyClass();
    }

    public IEnumerable<MyClass> GetAllMyClass()
    {
        // call private IQueryable so we can do attional "in-database" processing
        return this.ReadAllMyClass();
    }

    public IEnumerable<MyClass> GetActiveMyClass()
    {
        // call private IQueryable so we can do attional "in-database" processing
        // in this case a .Where() clause
        return this.ReadAllMyClass().Where(mc => mc.IsActive.Equals(true));
    }

    #region "Something my class MAY need to do in the future"
    private IQueryable<MyOtherTable> ReadAllMyOtherTable()
    {
        // there could be additional constrains which define
        // "all" for the current user
        return context.MyOtherTable;
    }

    public IEnumerable<MyOtherTable> GetAllMyOtherTable()
    {
        return this.ReadAllMyOtherTable();
    }

    public IEnumerable<MyOtherTable> GetInactiveOtherTable()
    {
        return this.ReadAllMyOtherTable.Where(ot => ot.IsActive.Equals(false));
    }
    #endregion

}

这种特殊情况并不是最好的说明,因为我可以直接在 GetActiveMyClass 方法中调用存储库,但我们假设我的私有 IQueryable 做了一些我不想在两者中复制的额外处理和业务逻辑我的公共方法。

这是解决此类问题的坏方法吗?我不认为它如此复杂以至于确实需要在存储库和服务类之间构建第三个类,但我想听听你的想法。

为了争论,我们假设另外两件事。

  1. 此服务将通过 WCF 公开,并且这些公共 IEnumerable 方法中的每一个都将在每个返回的集合上调用 .Select(m =&gt; m.ToViewModel()),这会将其转换为 POCO 以进行序列化。
  2. 服务最终需要公开一些context.SomeOtherTable,它们不会被包装到存储库中。

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    我认为这是一个很好的模型,因为您可以创建基本的 IQueryable 私有函数,这些函数可供您公开公开的函数使用。这样,您的公共方法不需要重新创建您的 IQueryable 方法执行的许多常见功能,并且可以根据需要扩展它们并延迟执行,同时仍然公开隐藏该功能。

    一个例子,比如如何从某个表中取出 X,这可能需要很多原始形式不需要的逻辑。然后,您将其作为私有方法,就像您在示例中所做的那样,然后公共方法添加最终标准或查询以生成一组可用的数据,这些数据可能因函数而异。为什么要一遍又一遍地重新发明轮子......只需创建基本设计(您的 IQueryable 所做的)并根据需要放置所需的胎面图案(您的公共 IEnumerable 所做的):)

    +1 为 IMO 提供出色的设计。

    【讨论】:

    • 这就是我希望听到的,谢谢。不过,我也希望能得到一些反对意见。
    • @Nate Bross 我想不出任何相反的观点,所以你应该走在正确的轨道上:)
    • 我想我是在找人说,no, you should really do xyz instead. 不是因为我认为我想出的东西不好,只是想看到一个好的案例来对抗它,看看我有没有站起来好不好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    相关资源
    最近更新 更多