需要一些关于POCO设计的建议和Lazy<>用于新架构

时间:2012-01-18 12:08:31

标签: c#-4.0 architecture lazy-loading poco composition

我面临着一个很难解决的架构决策。我很抱歉提前发帖,但在你能帮助我之前,我必须给你一个背景信息。

我的公司尝试将新架构(基于ASP.NET MVC框架)集成到现有的ASP.NET遗留代码中。提示是我们无法摆脱传统组件中封装的所有业务代码,但我们必须将其包装到新的代码中以形成一种“反腐败”层并将其解耦。我们到现在为止一直都很好,但是这里有一个约束(主要)使得解耦变得有点棘手:

  1. 在旧版ASP.NET网站中,他们使用了一种持久感知模型,以便从视图中启用延迟加载(我知道它是垃圾)。这是有原因的。代码令人沮丧并且难以部署,他们希望设计人员可以在不部署二进制文件的情况下仅修改视图。如果需要,可以使用延迟加载的属性将God类推入视图中。因此,例如,如果设计师想要修改视图以显示另一个属性,他可以从上帝班中选择他想要的东西并且它只是起作用。 我们必须在新的MVC架构中保持相同的行为
  2. 我们举一个例子。假设我们有一个Item 遗产持久感知DTO:

    public class Item
    {
       public string Title {get; set; }
       public List<UserComment> Comments {get; set; } // lazy loaded in the background in legacy code.
    }
    

    因此,设计人员在视图中使用可以调用Item.Title并进行部署,之后可以添加,如果他想要Item.Comments(在foreach中)并只部署视图而无需部署所有二进制文件。

    已提出以下架构。 mvc网站的新POCO位于Domain组件中,不引用任何其他组件。在这个程序集中,我们还有一个像IItemRepository这样的存储库接口的定义。实体直接在ASP.NET MVC ViewModels中使用,并通过由底层DI容器连接的Repository实现获得。

    我们还有另一个声明,即IRepositories的实现。该程序集引用了用于从域填充实体的所有遗留代码。

    直到现在一切都很棒。但这是棘手的部分。域程序集中的实体应符合第1点的约束(视图中的延迟加载)。

    因此我们的POCO将所有属性声明为Lazy&lt;&gt;。这允许我们在实现程序集(引用所有遗留代码的程序集)中定义在访问这些属性时填充这些属性的委托。以下是MVC的POCO的新实现:

    public class Item
        {
           public string Title {get; set; }
           public Lazy<List<UserComment>> Comments {get; set; } // lazy loaded in the background in legacy code.
        }
    

    这是一个ItemRepository实现:

    public class ItemRepository : IItemRepository
    {
        public Item GetItem(int id) 
        {
            Item i = new Item() { Id = id };
            i.Comments = new System.Lazy<IEnumerable<UserComments>>( () => CommentsService.GetUserComments(id));
    
            return i;
        }
    }
    

    我们不太喜欢它,这就是原因:

    • POCO并不是真正的POCO,因为实体中的生命管理似乎漏掉了抽象。这不是什么大问题,因为Lazy&lt;&gt;,是.NET Framework中的一种类型。另一方面,如果你正在使用像NHibernate这样的ORM,你必须弯曲你的POCO才能允许NHibernate加载数据(特殊构造函数,虚拟成员等)。
    • 我们不喜欢它的另一个原因是它隐藏了存储库实现中的底层服务组合。例如,如果使用Item.Comments,则在ItemRepository的底层实现中,我们将调用另一个旧服务(在这种情况下为CommentsService.GetUserComments(id))

    问题1:您是否看到使用Lazy&lt;&gt;的其他缺点在POCO实施中?或者我们应该考虑设计中的其他缺陷?

    问题2:我们如何避免存储库实施中的遗留服务组合,以便有一个明确的“愿景”    使用遗留服务?此外,我们真的需要这个“愿景”    在实施层面,因为我们可以考虑存储库    实现为传统服务的“外观”?

    问题3:关于约束1(延迟加载)还有其他选择吗?

    问题4:是否有与懒惰成员的构成相关的指南?

    对于长时间的问题,我很抱歉,但非常感谢您的帮助。

    托马斯

1 个答案:

答案 0 :(得分:2)

延迟加载属性是否必须为List<T>?如果没有,您可以将其定义为IList<T>ICollection<T>,如下所示:

public class Item
{
   public string Title {get; set; }
   public IList<UserComment> Comments {get; set; }
}

现在,由于该属性是接口的实例,您可以从中创建虚拟代理。