【问题标题】:WebAPI - using Unity with Ioc across multiple projectsWebAPI - 在多个项目中使用 Unity 和 Ioc
【发布时间】:2017-01-11 11:32:19
【问题描述】:

我有一个包含多个项目的解决方案 - 类似于以下内容:

  • WebAPI
    • ICustomerService.cs
  • 业务逻辑
    • CustomerService.cs
    • IDatabaseService.cs
  • 数据库访问
    • DatabaseService.cs

以前,WebAPI 项目引用了业务逻辑,然后引用了数据库访问。我试图颠倒这个逻辑。

目前,我在我的 WebAPI 项目中使用 Unity 来通过业务逻辑层的实现来解析接口,但是一旦我反转了我的逻辑,以便业务逻辑层具有对 WebAPI 层的引用,Unity 注册不会'没有循环引用就无法工作:

var container = new UnityContainer();
container.RegisterType<ICustomerService, CustomerService>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);

当我尝试注册我的类型时,ICustomerService 位于顶层项目中,CustomerService 对它是不可见的。

我读过关于有一个单独的项目来容纳统一配置,但这也会创建一个循环引用。我怎样才能做到这一点?

【问题讨论】:

    标签: c# asp.net-web-api unity-container


    【解决方案1】:

    你为什么要反转它?在我看来,这是唯一的方法。 WebAPI 项目是主要入口(如果它是自托管的,它将包含一个programs.cs)。该项目还将包含您的组合根,用于设置依赖注入和解析类型(这由 WebAPI 处理)。另见Composition Root。你能向我解释一下这样做的好处吗?

    还要注意,分散 IoC 容器跨项目是一种不好的做法。只有组合根(主)应该知道正在使用 Unity 的事实。还要避免使用 ServiceLocator 模式。

    不同项目中的对象应该仅通过构造函数具有引用/依赖关系。

    如果您认为Controller 依赖于ICustomService,那么CustomerService 依赖于IDatabaseService

    另外请注意:我会将实现和接口放在同一个项目中。

    WebAPI

    • 控制器

    业务逻辑

    • ICustomerService.cs
    • CustomerService.cs

    数据库访问

    • IDatabaseService.cs
    • DatabaseService.cs

    【讨论】:

    • 感谢 cmets,我想这样做的原因是为了支持业务逻辑和下层的灵活性。我把它放在一个正在变化的 ERP 系统之上,两个系统将并行运行一段时间。我希望依赖注入器是智能的,以便将服务从一个系统移动到另一个系统,我可以设置逻辑以了解“您使用 CustomerServiceA.cs”和“您使用 CustomerServiceB.cs” - 也许我正在考虑这个走错路了?
    • 所以您希望能够在不重新编译的情况下更改业务逻辑层?
    • 很快会有第二个业务逻辑和数据库访问层,我希望能够以编程方式选择我想使用的那个,但是 webapi 不应该知道它将是哪个实现使用
    • 通常您会使用类似 XML 配置的东西来执行此操作。见XML configuraiont。如果这是一个要求,您不应该在同一个 dll 中拥有实现和接口。我也可以推荐这本书:Dependency Injection in .NET
    【解决方案2】:

    你走在正确的道路上。您的控制器应在构造函数中注入 icustomerservice 实现,而服务应在其构造函数中注入 idatabaseservice。

    public FooController(ICustomerService svc)
    ...
    public CustomerService(IDatabaseService db)
    ...
    

    并添加数据库DI配置

    container.RegisterType<IDatabaseService, DatabaseService>();
    container.RegisterType<ICustomerService, CustomerService>();
    

    当您准备好使用新实现时,只需更改配置中的引用以实例化新实现。

    接口应该在一个项目中,实现应该在一个项目中。新旧实现应该共享一个通用接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多