... похоже, что в ядре архитектуры есть репозитории, которые реализуют инфраструктуру как зависимости, не противоречит ли это?
Здесь вам не хватает интерфейсов. Возьмем 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 определяется на уровне инфраструктуры:
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, определенному на уровне Application Core. IOrderRepository снова является производным от IAsyncRepository, который также определен на уровне Application Core.
Я предполагаю, что причина, по которой они используют IAsyncRepository, а не IOrderRepository в OrderService, заключается в том, что к настоящему времени метод OrderService обращается только к методам, определенным базовым интерфейсом IAsyncRepository.
Но идея остается той же: все на уровне ядра приложения должно иметь зависимости только от материалов того же уровня. Затем конкретные реализации вводятся во время выполнения посредством внедрения зависимостей. Но самому уровню Application Core никогда не нужно ничего знать о реальной реализации, находящейся на уровне инфраструктуры.
И если вы последуете этому подходу, утверждение
... ядро приложения находится в центре, а внешние уровни указывают внутрь с точки зрения зависимостей.
остается верным, поскольку внешние уровни зависят от классов и интерфейсов из Application Core, а Application Core зависит только от - Application Core.
person
afh
schedule
11.08.2020