【问题标题】:Avoid cross project dependencies in onion architecture避免洋葱架构中的跨项目依赖
【发布时间】:2020-03-23 04:54:23
【问题描述】:

我有一个遵循此图的洋葱架构:

其中每个项目通过接口连接到“中心”。

现在,我处于支付网关需要存储一些数据的情况。如果它可以访问数据库,那就太棒了,但我意识到我不能直接连接它们,这会破坏“洋葱”结构! (以及 IoC 原则!)

因此,似乎解决方案是创建一个接口,我将在持久性中实现该接口,并将其传递给 PaymentGateway。这将允许它保存自己的东西。但是这个接口可能必须非常具体(即void SavePaymentGatewayCustomer(Customer customer);void SavePaymentGatewayCustomerPaymentMethod(PaymentMethod paymentMethod);,对我来说这也破坏了 IoC,因为持久性和“中心”都知道太多关于 PaymentGateway 的信息。

好像大家迟早都会遇到的问题,不知道你是怎么解决的。


附加信息:

解的结构是:

接口在“AbstractionLayer”项目中定义,如下所示:

public interface IUsersPersistenceHandler : IDisposable
{
    /// <summary> Gets the user. </summary>
    /// <param name="id">The user identifier.</param>
    Result<IUser> GetUser(string id);

    ...
}

这些接口然后由外围项目实现:

public sealed class VolatileUserPersistenceHandler : IUsersPersistenceHandler
{
    private readonly Dictionary<string, Individual> _individuals;
    private readonly Dictionary<string, Organization> _organizations;

    /// <inheritdoc />
    public Result<IUser> GetUser(string id) { ... }
    ...
}

通过依赖注入,实现被注入到 API 级别,这样对外部项目一无所知,只知道接口(通过这种方式,可以轻松地将数据库持久性与易失性持久性交换. 或者支付网关可以替换为另一个,而无需重写所有内容)。

这是简单的情况。当 PaymentGateway 需要能够存储/检索自己的信息时,就会出现问题。

假设 PaymentGateway 有自己的用户定义。现在我们要将我们的用户(在 CORE 中)与网关相关联,并且我们希望将信息保存在某处。
例如,PaymentGateway 中的用户有一个string GatewayIdstring CustomerId,我们需要将它们存储在某个地方。

记住,情况是这样的:CORE 不想知道细节实现的任何事情!它只知道接口知道什么。

【问题讨论】:

  • 您能否包含一些代码以更好地展示您要询问的内容?到目前为止,您的图表是您所拥有的一个很好的高水平,但我正试图掌握您遇到问题的地方。
  • @Nkosi 完成。希望这就够了。

标签: c# architecture dependencies inversion-of-control onion-architecture


【解决方案1】:

洋葱架构描述了一个应用程序。洋葱之外的系统是其他应用程序。

  • 数据库在另一个进程中运行,通常在不同的机器上
  • 邮件系统在另一个进程中运行,通常在不同的机器上
  • 支付网关(我推测)在另一个进程中运行,通常是 Internet 上的其他地方
  • 等等……

支付网关可能有持久性需求,但这应该与相关应用程序使用的持久性引擎无关。

如果您使用洋葱架构构建的应用程序需要在持久性系统中持久化来自支付网关的一些数据,那么有责任这样做.在这种情况下,Core 中必须有一些应用程序代码(或下一层的“控制器”层)来处理它。

详细了解 Onion 架构和依赖注入 here

【讨论】:

  • 也许在我的图中,“浮动”实体看起来很遥远,而实际上,它们仍然是洋葱的一部分。 PaymentGateway 只是描述应用程序如何与外部网关通信的几个类,邮件系统也是如此。我不希望外部 PaymentGateway 与我的数据库通信,我希望我自己的代码,引用它,可以存储一些数据。
  • @AlvinSartor 在这种情况下,请关注DIP。编写执行您希望它执行的代码的代码,查看它需要哪些依赖项,然后添加它们。客户端代码拥有接口,而不是相反。
猜你喜欢
  • 2013-01-31
  • 1970-01-01
  • 2015-05-19
  • 2017-11-23
  • 2011-12-08
  • 1970-01-01
  • 2011-10-09
  • 2014-10-15
  • 1970-01-01
相关资源
最近更新 更多