代码之家  ›  专栏  ›  技术社区  ›  Nate CSS Guy

一些私有方法公开iQuery<t>和所有公共方法公开IEnumerable<t>有什么问题吗?

  •  9
  • Nate CSS Guy  · 技术社区  · 14 年前

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

    假设我有一个linq-to-sql数据上下文,我编写了一个“知识库风格”类,它包含了我需要的许多方法,并公开了iqueryables。(到目前为止,没问题)。

    现在,我正在构建一个服务层来放置在这个存储库的顶部,其中许多服务方法将是1<->1和存储库方法,但有些方法不会。我认为代码示例比文字更能说明这一点。

    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 => m.ToViewModel()) 在每个返回的集合上,将其转换为POCO进行序列化。
    2. 服务最终需要公开一些 context.SomeOtherTable 不会被打包到存储库中。
    1 回复  |  直到 14 年前
        1
  •  5
  •   Kelsey    14 年前

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

    例如,如何从某个表中获取X,这可能需要大量的逻辑,而这些逻辑在原始表单中是不需要的。然后将其作为私有方法,就像在示例中那样,然后公共方法添加终结条件或查询,以生成一组可用的数据,这些数据可能因函数而异。为什么不停地重新发明轮子…只需创建基本设计(您iQuery所做的)并根据需要放置所需的胎面花纹(您的公共IEnumerable所做的):)

    +一个好的设计。