【问题标题】:Cyclic Dependency between Infrastructure and Model Layers/projects of DDDDDD的基础设施和模型层/项目之间的循环依赖
【发布时间】:2013-09-19 17:12:49
【问题描述】:

我正在关注 C#.NEt 中的域驱动模型一书。我在基础架构和域层之间存在循环依赖关系(两者都是我的解决方案的类库项目,即“ShareManagement”)。我想知道如何摆脱 Visual Studio/C#.NET 中的循环依赖问题。

  1. 模型对基础设施层的依赖: 当然,域层使用基础设施层,这样模型层中的对象依赖(调用)基础设施层中的对象(如基础设施层中定义的存储库使用ICompanyRepository 从域模型层访问,它实现了基础设施层中定义的IRepository<T>)。

  2. 基础设施对领域模型类的依赖: 但是,在基础设施层中,我的实体框架(实体工厂)需要实现IEntityFactory<T>,其中TEntityBase(域模型层中的实体类派生自基础设施层中的EntityBase;EntityBase 是所有实体的基类) .

以下是基础设施层中的类(在“Repositories”文件夹下):

using System.Text;
using System.Data;
using ShareManagement.Model.Company; // How to do this ??
ShareManagement.Infrastructure.EntityFactoryFramework;

namespace ShareManagement.Infrastructure.Repositories
{
    internal class CompanyFactory: IEntityFactory<Company> 
//Company is defined in Model Layer and derived from Abstract Base class "EntityBase"
//So, how to use "using ShareManagement.Model.Company" ?
    {

    }
}

【问题讨论】:

  • 严格来说,域不应依赖于任何基础设施或应用程序级服务。也许,onion architecture 的文章会是一个很好的参考。
  • 你怎么能说当域模型层包含实体类时,所有这些实体类都派生自一个公共基类“EntityBase”,该基类在 InfraStructure Layer 中定义,据我所知,“使用 myProjectName.基础设施.DomainBase;"在域模型层中,我们必须将域模型层项目中的引用/依赖添加到基础设施层。请参阅下面的代码,其中我需要使用命名空间( using System; using SmartCA.Infrastructure.DomainBase; using SmartCA.Model.Companies; namespace SmartCA.Model.Projects { public class Contract : EntityBase {
  • 再次,严格地说,实体不应该派生自基类(除非您正在建模需要继承的关系)。你也看过我链接的文章吗?
  • EntityBase:Evans 将 Entity 定义为“通过身份而不是属性来区分的对象”(Evans,Domain-Driven Design:Tackling Complexity in the Heart of Software,92),所有的实体类需要某种类型的数据类型来区分它们的身份。最好使用 Fowler 的分层超类型模式,该模式被定义为“充当其层中所有类型的超类型的类型”(Fowler,企业应用程序架构模式,475 ).让所有实体都继承自实体基类类型将有助于消除域实体类中的一些重复属性和行为。
  • 除了我上面的解释:我的问题不在于模型是否应该使用/依赖于基础设施,或者实体是否应该从 EntityBase 派生。我的问题实际上是如何在基础设施层中使用模型层/项目中的命名空间(我是 Visual Studio 和 .NET 的新手,所以我尝试在基础设施层项目中创建对模型层的依赖项/引用,但因为模型层已经有了引用基础设施层,因此存在循环依赖问题。我不知道如何解决这种情况。

标签: c# model infrastructure cyclic-dependency


【解决方案1】:

下面链接中显示的图像有两个组件/项目(包含在两个主要边界中),分别命名为 Infrastructure Layer Project/Assembly 和 Model Layer Prject/Assembly。

从图中可以明显看出,它们都形成了循环依赖。 http://screencast.com/t/lUGwetETXHF

此问题的解决方案如下面的链接所示: http://screencast.com/t/acsLjq7Ubd

如果项目/程序集 A(在我们的例子中是模型)依赖(引用)项目/程序集 B(在我们的例子中是基础设施)并且如果 “part-of” 程序集 B(例如, Infrastructure.Repositories OR EntityFactory)依赖于(;需要引用)项目/程序集 A(模型)中的类,形成循环依赖关系,然后按如下方式解决此依赖关系:

为了便于理解,我们将Assembly B中依赖的“Part-Of Code”命名为B-dep1;

  1. 使 B-dep1 成为与 B ShareManagement.Infrastructure.Repositories 分开的程序集/项目。

  2. B-dep1 的新项目的名称应该与项目 B 中层的名称空间名称相同,这样 B-dep1 仍然是层/命名空间的一部分(我的意思是,它仍然是ShareManagement.Infrastructure 命名空间)在 Assembly/Project B 中。(在我们的例子中,我将 B-dep1 的这个新项目命名为 ShareManagement.Infrastructure.Repositories。

  3. 现在,B-dep1 的新项目,即“ShareManagement.Infrastructure.Repositories”可以引用 A 而不会形成循环依赖。

查看方法:

B-dep1 的新项目,即“ShareManagement.Infrastructure.Repositories”依赖于 A。 在 B 上,但 B 不依赖于(引用)New-Part Project。

A 依赖于 B 但 B 不依赖于 B-dep1 的新项目,即“ShareManagement.Infrastructure.Repositories” 而 ShareManagement.Infrastructure.Repositories 项目仍然可以继续使用基础设施层的名称空间(和封装的代码),而无需添加对基础设施代码的引用,因为它们具有相同的名称空间(这就是为什么我将项目命名为 B 项目中的名称空间) . Visual Studio 根据项目名称或文件夹名称自动创建命名空间。不同程序集中的相同命名空间释放程序集以相互引用,就像在这种情况下与基础设施层相关的命名空间一样。

【讨论】:

    猜你喜欢
    • 2017-06-10
    • 2013-01-13
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 2014-08-17
    • 2021-11-22
    相关资源
    最近更新 更多