【问题标题】:Clean/onion architecture in .NET core question.NET 核心问题中的清洁/洋葱架构
【发布时间】:2020-08-13 18:17:57
【问题描述】:

我有几个关于干净/洋葱架构的问题。我一直在阅读 Microsoft 文档,它指出应用程序核心位于中心,而外层在“依赖项”方面指向内部。

当它在这种情况下依赖时,它们到底是什么意思?当我想到依赖项时,我认为 B 类在 A 类内部被实例化,因此 A 类依赖于 B 类。但是,当我查看 eShopOnWeb 存储库 (https://github.com/dotnet-architecture/eShopOnWeb) 时,看起来架构核心具有将基础设施作为依赖项实现的 repos,这不是矛盾的吗?

【问题讨论】:

标签: asp.net .net asp.net-core .net-core clean-architecture


【解决方案1】:

在这种情况下,A 依赖于 B 意味着:A “知道” B。

内圈的类型可以被外圈的类型使用,反之则不行。

也请参考:https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

【讨论】:

    【解决方案2】:

    ...看起来架构核心具有正在作为依赖项实现基础架构的 repos,这不是矛盾的吗?

    您在这里缺少的是接口的使用。让我们看看应用程序核心层的OrderService

    namespace Microsoft.eShopWeb.ApplicationCore.Services
    {
        public class OrderService : IOrderService
        {
            private readonly IAsyncRepository<Order> _orderRepository;
            private readonly IUriComposer _uriComposer;
            private readonly IAsyncRepository<Basket> _basketRepository;
            private readonly IAsyncRepository<CatalogItem> _itemRepository;
    
            public OrderService(IAsyncRepository<Basket> basketRepository,
                IAsyncRepository<CatalogItem> itemRepository,
                IAsyncRepository<Order> orderRepository,
                IUriComposer uriComposer)
            {
                _orderRepository = orderRepository;
                _uriComposer = uriComposer;
                _basketRepository = basketRepository;
                _itemRepository = itemRepository;
            }
    
            public async Task CreateOrderAsync(int basketId, Address shippingAddress)
            {
                var basketSpec = new BasketWithItemsSpecification(basketId);
                var basket = await _basketRepository.FirstOrDefaultAsync(basketSpec);
    
                Guard.Against.NullBasket(basketId, basket);
                Guard.Against.EmptyBasketOnCheckout(basket.Items);
    
                var catalogItemsSpecification = new CatalogItemsSpecification(basket.Items.Select(item => item.CatalogItemId).ToArray());
                var catalogItems = await _itemRepository.ListAsync(catalogItemsSpecification);
    
                var items = basket.Items.Select(basketItem =>
                {
                    var catalogItem = catalogItems.First(c => c.Id == basketItem.CatalogItemId);
                    var itemOrdered = new CatalogItemOrdered(catalogItem.Id, catalogItem.Name, _uriComposer.ComposePicUri(catalogItem.PictureUri));
                    var orderItem = new OrderItem(itemOrdered, basketItem.UnitPrice, basketItem.Quantity);
                    return orderItem;
                }).ToList();
    
                var order = new Order(basket.BuyerId, shippingAddress, items);
    
                await _orderRepository.AddAsync(order);
            }
        }
    }
    

    应用核心中定义的OrderService只有对接口的依赖应用程序核心。

    比如有

    private readonly IAsyncRepository<Order> _orderRepository;
    

    注入到OrderService的构造函数中。

    OrderRepository实现infrastructure层中定义

    namespace Microsoft.eShopWeb.Infrastructure.Data
    {
        public class OrderRepository : EfRepository<Order>, IOrderRepository
        {
            public OrderRepository(CatalogContext dbContext) : base(dbContext)
            {
            }
    
            public Task<Order> GetByIdWithItemsAsync(int id)
            {
                return _dbContext.Orders
                    .Include(o => o.OrderItems)
                    .Include($"{nameof(Order.OrderItems)}.{nameof(OrderItem.ItemOrdered)}")
                    .FirstOrDefaultAsync(x => x.Id == id);
            }
        }
    }
    

    基础设施类OrderRepository 遵循应用程序核心层中定义的IOrderInterface 契约。 IOrderRepository 再次派生自 IAsyncRepository,它也在应用程序核心层中定义。

    我猜他们在 OrderService 中使用 IAsyncRepository 而不是 IOrderRepository 的原因是,现在 OrderService 方法只访问由基本接口 IAsyncRepository 定义的方法。

    但想法保持不变:应用程序核心层中的所有内容都应仅依赖于同一层中的内容。具体实现是通过依赖注入在运行时注入的。但应用程序核心层本身并不需要了解基础设施层中的“真实”实现。

    如果你遵循这种方法,那么声明

    ...应用程序核心位于中心,外层根据“依赖关系”指向内部。

    仍然如此,因为外层依赖于应用程序核心的类和接口,而应用程序核心仅依赖于应用程序核心。

    【讨论】:

      猜你喜欢
      • 2022-09-24
      • 2014-06-22
      • 1970-01-01
      • 1970-01-01
      • 2014-01-25
      • 2011-10-09
      • 1970-01-01
      • 2014-12-22
      • 2014-10-15
      相关资源
      最近更新 更多