避免洋葱架构中的跨项目依赖

Avoid cross project dependencies in onion architecture

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

其中每个项目都通过接口连接到 "center"。

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

因此,似乎解决方案是创建一个接口,我将在持久性中实现该接口并将其传递到 PaymentGateway。这将允许它保存自己的东西。但是这个接口可能必须非常具体(即 void SavePaymentGatewayCustomer(Customer customer);void SavePaymentGatewayCustomerPaymentMethod(PaymentMethod paymentMethod);,对我来说这也破坏了 IoC,因为 Persistence 和 "center" 都知道关于 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) { ... }
    ...
}

通过Dependency Injection,将实现注入到API级别,这样就不知道任何外部项目,只知道接口(这样,数据库持久化很容易用不稳定的持久性交换。或者支付网关可以用另一个替换,而不必重写所有内容)。

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

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

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

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

  • 数据库在另一个进程中运行,通常在不同的机器上
  • 邮件系统在另一个进程中运行,通常在不同的机器上
  • 支付网关(我假设)在另一个进程中运行,通常在互联网上的其他地方
  • 等等...

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

如果您使用洋葱架构构建的应用程序以某种方式需要在 its 持久性系统中保存来自支付网关的一些数据,则 its这样做的责任。那么,在那种情况下,Core(或下一层的 'controller' 层)中必须有一些应用程序代码来处理该问题。

阅读更多关于洋葱架构和依赖注入的信息here