Browse Source

Refactoring Domain Events

pull/126/head
Cesar De la Torre 8 years ago
parent
commit
c7e317413e
12 changed files with 62 additions and 59 deletions
  1. +36
    -0
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerPaymentMethodVerifiedDomainEventHandler.cs
  2. +5
    -5
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedDomainEventHandler.cs
  3. +0
    -33
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/PaymentMethodCheckedDomainEventHandler.cs
  4. +1
    -1
      src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
  5. +3
    -3
      src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
  6. +6
    -6
      src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs
  7. +2
    -2
      src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs
  8. +2
    -2
      src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs
  9. +1
    -1
      src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs
  10. +2
    -2
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
  11. +2
    -2
      test/Services/UnitTest/Ordering/Domain/BuyerAggregateTest.cs
  12. +2
    -2
      test/Services/UnitTest/Ordering/Domain/OrderAggregateTest.cs

+ 36
- 0
src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerPaymentMethodVerifiedDomainEventHandler.cs View File

@ -0,0 +1,36 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging;
using Ordering.Domain.Events;
using System;
using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers
{
public class BuyerPaymentMethodVerifiedDomainEventHandler : IAsyncNotificationHandler<BuyerPaymentMethodVerifiedDomainEvent>
{
private readonly IOrderRepository<Order> _orderRepository;
private readonly ILoggerFactory _logger;
public BuyerPaymentMethodVerifiedDomainEventHandler(IOrderRepository<Order> orderRepository, ILoggerFactory logger)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
// Domain Logic comment:
// When the Buyer and Buyer's payment method have been created or verified that they existed,
// then we can update the original Order with the BuyerId and PaymentId (foreign keys)
public async Task Handle(BuyerPaymentMethodVerifiedDomainEvent buyerPaymentMethodVerifiedEvent)
{
var orderToUpdate = await _orderRepository.GetAsync(buyerPaymentMethodVerifiedEvent.OrderId);
orderToUpdate.SetBuyerId(buyerPaymentMethodVerifiedEvent.Buyer.Id);
orderToUpdate.SetPaymentId(buyerPaymentMethodVerifiedEvent.Payment.Id);
await _orderRepository.UnitOfWork
.SaveEntitiesAsync();
_logger.CreateLogger(nameof(BuyerPaymentMethodVerifiedDomainEventHandler))
.LogTrace($"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }");
}
}
}

src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCreatedDomainEventHandler.cs → src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedDomainEventHandler.cs View File

@ -8,20 +8,20 @@ using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers
{
public class OrderCreatedDomainEventHandler : IAsyncNotificationHandler<OrderCreatedDomainEvent>
public class OrderStartedDomainEventHandler : IAsyncNotificationHandler<OrderStartedDomainEvent>
{
private readonly ILoggerFactory _logger;
private readonly IBuyerRepository<Buyer> _buyerRepository;
private readonly IIdentityService _identityService;
public OrderCreatedDomainEventHandler(ILoggerFactory logger, IBuyerRepository<Buyer> buyerRepository, IIdentityService identityService)
public OrderStartedDomainEventHandler(ILoggerFactory logger, IBuyerRepository<Buyer> buyerRepository, IIdentityService identityService)
{
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderCreatedDomainEvent orderNotification)
public async Task Handle(OrderStartedDomainEvent orderNotification)
{
var cardTypeId = orderNotification.CardTypeId != 0 ? orderNotification.CardTypeId : 1;
@ -33,7 +33,7 @@ namespace Ordering.API.Application.DomainEventHandlers
buyer = new Buyer(buyerGuid);
}
var payment = buyer.AddPaymentMethod(cardTypeId,
var paymentMethod = buyer.VerifyOrAddPaymentMethod(cardTypeId,
$"Payment Method on {DateTime.UtcNow}",
orderNotification.CardNumber,
orderNotification.CardSecurityNumber,
@ -46,7 +46,7 @@ namespace Ordering.API.Application.DomainEventHandlers
await _buyerRepository.UnitOfWork
.SaveEntitiesAsync();
_logger.CreateLogger(nameof(OrderCreatedDomainEventHandler)).LogTrace($"A new payment method has been successfully added for orderId: {orderNotification.Order.Id}.");
_logger.CreateLogger(nameof(OrderStartedDomainEventHandler)).LogTrace($"A new payment method has been successfully added for orderId: {orderNotification.Order.Id}.");
}
}

+ 0
- 33
src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/PaymentMethodCheckedDomainEventHandler.cs View File

@ -1,33 +0,0 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging;
using Ordering.Domain.Events;
using System;
using System.Threading.Tasks;
namespace Ordering.API.Application.DomainEventHandlers
{
public class PaymentMethodCheckedDomainEventHandler : IAsyncNotificationHandler<PaymentMethodCheckedDomainEvent>
{
private readonly IOrderRepository<Order> _orderRepository;
private readonly ILoggerFactory _logger;
public PaymentMethodCheckedDomainEventHandler(IOrderRepository<Order> orderRepository, ILoggerFactory logger)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(PaymentMethodCheckedDomainEvent paymentMethodNotification)
{
var orderToUpdate = await _orderRepository.GetAsync(paymentMethodNotification.OrderId);
orderToUpdate.SetBuyerId(paymentMethodNotification.Buyer.Id);
orderToUpdate.SetPaymentId(paymentMethodNotification.Payment.Id);
await _orderRepository.UnitOfWork
.SaveEntitiesAsync();
_logger.CreateLogger(nameof(PaymentMethodCheckedDomainEventHandler))
.LogTrace($"Order with Id: {paymentMethodNotification.OrderId} has been successfully updated with a new payment method id: { paymentMethodNotification.Payment.Id }");
}
}
}

+ 1
- 1
src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs View File

@ -24,7 +24,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
.Select(i => new KeyedService("IAsyncRequestHandler", i)));
builder
.RegisterAssemblyTypes(typeof(OrderCreatedDomainEventHandler).GetTypeInfo().Assembly)
.RegisterAssemblyTypes(typeof(OrderStartedDomainEventHandler).GetTypeInfo().Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>)))
.AsImplementedInterfaces();


+ 3
- 3
src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs View File

@ -24,7 +24,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity));
}
public PaymentMethod AddPaymentMethod(
public PaymentMethod VerifyOrAddPaymentMethod(
int cardTypeId, string alias, string cardNumber,
string securityNumber, string cardHolderName, DateTime expiration, int orderId)
{
@ -33,7 +33,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
if (existingPayment != null)
{
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, existingPayment, orderId));
AddDomainEvent(new BuyerPaymentMethodVerifiedDomainEvent(this, existingPayment, orderId));
return existingPayment;
}
else
@ -41,7 +41,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
_paymentMethods.Add(payment);
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, payment, orderId));
AddDomainEvent(new BuyerPaymentMethodVerifiedDomainEvent(this, payment, orderId));
return payment;
}
}


+ 6
- 6
src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs View File

@ -52,10 +52,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_orderDate = DateTime.UtcNow;
Address = address;
// Add the OrderCreatedEvent to the domain events collection
// Add the OrderStarterDomainEvent to the domain events collection
// to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ]
AddOrderCreatedDomainEvent(cardTypeId, cardNumber,
cardSecurityNumber, cardHolderName, cardExpiration);
AddOrderStartedDomainEvent(cardTypeId, cardNumber,
cardSecurityNumber, cardHolderName, cardExpiration);
}
// DDD Patterns comment
@ -96,14 +96,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_buyerId = id;
}
private void AddOrderCreatedDomainEvent(int cardTypeId, string cardNumber,
private void AddOrderStartedDomainEvent(int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
{
var orderCreatedDomainEvent = new OrderCreatedDomainEvent(
var orderStartedDomainEvent = new OrderStartedDomainEvent(
this, cardTypeId, cardNumber, cardSecurityNumber,
cardHolderName, cardExpiration);
AddDomainEvent(orderCreatedDomainEvent);
this.AddDomainEvent(orderStartedDomainEvent);
}
}
}

src/Services/Ordering/Ordering.Domain/Events/PaymentMethodCheckedDomainEvent.cs → src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs View File

@ -6,14 +6,14 @@ using System.Text;
namespace Ordering.Domain.Events
{
public class PaymentMethodCheckedDomainEvent
public class BuyerPaymentMethodVerifiedDomainEvent
: IAsyncNotification
{
public Buyer Buyer { get; private set; }
public PaymentMethod Payment { get; private set; }
public int OrderId { get; private set; }
public PaymentMethodCheckedDomainEvent(Buyer buyer, PaymentMethod payment, int orderId)
public BuyerPaymentMethodVerifiedDomainEvent(Buyer buyer, PaymentMethod payment, int orderId)
{
Buyer = buyer;
Payment = payment;

src/Services/Ordering/Ordering.Domain/Events/OrderCreatedDomainEvent.cs → src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs View File

@ -9,7 +9,7 @@ namespace Ordering.Domain.Events
/// <summary>
/// Event used when an order is created
/// </summary>
public class OrderCreatedDomainEvent
public class OrderStartedDomainEvent
: IAsyncNotification
{
public int CardTypeId { get; private set; }
@ -19,7 +19,7 @@ namespace Ordering.Domain.Events
public DateTime CardExpiration { get; private set; }
public Order Order { get; private set; }
public OrderCreatedDomainEvent(Order order,
public OrderStartedDomainEvent(Order order,
int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName,
DateTime cardExpiration)

+ 1
- 1
src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs View File

@ -8,7 +8,7 @@ namespace Ordering.Infrastructure
{
public static class MediatorExtension
{
public static async Task RaiseDomainEventsAsync(this IMediator mediator, OrderingContext ctx)
public static async Task DispatchDomainEventsAsync(this IMediator mediator, OrderingContext ctx)
{
var domainEntities = ctx.ChangeTracker.Entries<Entity>().Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any());
var domainEvents = domainEntities.SelectMany(x => x.Entity.DomainEvents).ToList();


+ 2
- 2
src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs View File

@ -239,8 +239,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
{
var result = await base.SaveChangesAsync();
// Dispatch the Domain Events collection right after saving/commiting data into the database
await _mediator.RaiseDomainEventsAsync(this);
// Dispatch the Domain Events collection right after saving/committing data into the database
await _mediator.DispatchDomainEventsAsync(this);
return result;
}
}


+ 2
- 2
test/Services/UnitTest/Ordering/Domain/BuyerAggregateTest.cs View File

@ -45,7 +45,7 @@ public class BuyerAggregateTest
var fakeBuyerItem = new Buyer(identity);
//Act
var result = fakeBuyerItem.AddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration, orderId);
var result = fakeBuyerItem.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration, orderId);
//Assert
Assert.NotNull(result);
@ -119,7 +119,7 @@ public class BuyerAggregateTest
//Act
var fakeBuyer = new Buyer(Guid.NewGuid().ToString());
fakeBuyer.AddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId);
fakeBuyer.VerifyOrAddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId);
//Assert
Assert.Equal(fakeBuyer.DomainEvents.Count, expectedResult);


+ 2
- 2
test/Services/UnitTest/Ordering/Domain/OrderAggregateTest.cs View File

@ -133,7 +133,7 @@ public class OrderAggregateTest
//Act
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
fakeOrder.AddDomainEvent(new OrderCreatedDomainEvent(fakeOrder,cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration));
fakeOrder.AddDomainEvent(new OrderStartedDomainEvent(fakeOrder,cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration));
//Assert
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult);
}
@ -153,7 +153,7 @@ public class OrderAggregateTest
var cardHolderName = "FakeName";
var cardExpiration = DateTime.Now.AddYears(1);
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var @fakeEvent = new OrderCreatedDomainEvent(fakeOrder, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var @fakeEvent = new OrderStartedDomainEvent(fakeOrder, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var expectedResult = 1;
//Act


Loading…
Cancel
Save