Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IOC和接口_C#_C# 4.0_Dependency Injection_Inversion Of Control - Fatal编程技术网

C# IOC和接口

C# IOC和接口,c#,c#-4.0,dependency-injection,inversion-of-control,C#,C# 4.0,Dependency Injection,Inversion Of Control,我的项目结构如下:- CentralRepository.BL CentralRepository.BO CentralRepository.DataAccess CentralRepository.Tests CentralRepository.Webservices 这两者之间存在着大量的依赖关系。我想利用unity来减少依赖性,所以我将为我的类创建接口。我的问题是接口应该驻留在哪个项目中。我的想法是它们应该在BO层。有人能给我一些指导吗?BO本质上是你的域对象,或者至少这是我的假设。通常

我的项目结构如下:-

CentralRepository.BL
CentralRepository.BO
CentralRepository.DataAccess
CentralRepository.Tests
CentralRepository.Webservices

这两者之间存在着大量的依赖关系。我想利用unity来减少依赖性,所以我将为我的类创建接口。我的问题是接口应该驻留在哪个项目中。我的想法是它们应该在BO层。有人能给我一些指导吗?BO本质上是你的域对象,或者至少这是我的假设。通常,除非您使用类似ActiveRecord的模式,否则它们只是状态对象。另一方面,接口指定行为。从许多“最佳实践”来看,将行为和状态混为一谈不是一个好概念。现在我可能会漫谈一下,但我认为背景可能会有所帮助

现在,我们来讨论接口应该存在于何处的问题。有两种选择

  • 将接口粘贴到它们所属的库中
  • 创建一个单独的合同库
  • 更简单的方法是将它们放在同一个库中,但是您的模拟依赖于库以及您的测试。没什么大不了的,但它有一点味道

    我通常的方法是设置如下项目:

    {公司}.{计划/项目}.{关注点(可选)}.{区域}.{分区(可选)}

    名字的前两到三位在你的名字中被“CentralRepository”一词所覆盖。在我的例子中,可能是MyCompany.CentralRepository或MyCompany.MyProgram.CentralRepository,但命名约定不是本文的核心部分

    “区域”部分是这篇文章的主旨,我通常使用以下内容

  • 设置域对象库(您的BO):CentralRepository.domain.Models
  • 设置域异常库:CentralRepository.domain.Exceptions
  • 所有/大多数其他项目都引用上述两个,因为它们代表应用程序中的状态。当然,所有业务库都使用这些对象。持久性库可能有不同的模型,而我可能在体验库上有一个视图模型
  • 接下来设置核心库:CentralRepository.core(可能有子区域?)。这就是业务逻辑的所在(实际的应用程序,因为持久性和体验的变化不应该影响核心功能)
  • 为核心设置一个测试库:CentralRepository.core.test.Unit.VS(我用Unit.VS来显示这些是单元测试,而不是与单元测试库的集成测试,我用VS来表示MSTest-其他将有不同的命名)
  • 创建测试,然后设置业务功能。根据需要,设置接口。范例
  • 需要来自DAL的数据,因此为核心测试使用的数据设置了接口和模拟。这里的名称类似于CentralRepository.Persist.Contracts(如果存在多种类型的持久性,也可以使用子区域)
  • 这里的核心概念是“作为应用程序的核心”,而不是n层(它们是兼容的,但仅将业务逻辑作为一种范例来考虑,会使您与持久性和体验松散耦合)

    现在,回到你的问题上来。我设置接口的方式基于“接口”类的位置。因此,我可能会:

    CentralRepository.Core.Contracts CentralRepository.Experience.Service.Contracts CentralRepository.Persist.Service.Contracts CentralRepository.Persist.Data.Contracts

    我仍在处理这个问题,但核心概念是我的IoC,应该同时考虑测试,我应该能够隔离测试,如果我能够隔离合同(接口),这将更好地实现。逻辑分离很好(单个库),但我通常不会这样做,因为至少有几个绿色开发人员发现,如果没有物理分离,很难看到逻辑分离。您的里程数可能会有所不同-0


    希望这段漫无边际的谈话能有所帮助

    如果你说的是程序集,我建议在大多数情况下,在实现者所在的位置保留接口

    就我个人而言,当我使用分层方法时,我倾向于为每个层提供自己的组件,并为其下面的层提供一个引用。在每一层中,大多数公共事物都是接口。因此,在数据访问层中,我可以使用icCustomerDAO和IOrderDao作为公共接口。我还将在Dao组装中拥有公共Dao工厂。然后,我将把实现公共接口的特定实现标记为internal--CustomerDaoMySqlImpl或customerdaomxmlimpl。然后,公共工厂向用户(即域层)提供实现,而用户不知道他们得到的是哪一个实现——他们向工厂提供信息,工厂转身递给他们一个他们使用的ICCustomerDAO

    我之所以提到这一切,是为了理解接口应该是什么样的基础——API的服务和客户端之间的契约。因此,从依赖关系的角度来看,您希望在服务者所在的位置定义契约。如果您在其他地方定义它,那么您可能不会真正使用接口管理依赖关系,而只是引入了一个无用的间接层


    所以无论如何,我要说的是,把你的接口想象成它们是什么——一份关于你将要提供什么的合同,同时对你将如何提供它的细节保密。这可能是一个很好的启发,可以让界面放置在更直观的位置。

    在组合层次上,您有三个选择:

    • 在单独的库中定义接口
    • 与用户一起定义接口
    • 定义接口及其实现者
    然而,最后一个选项是一个非常糟糕的主意,因为它将接口与实现者紧密耦合(或者反过来)。因为首先引入接口的全部目的是