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 namespace Ordering.API.Application.DomainEventHandlers
{ {
public class OrderCreatedDomainEventHandler : IAsyncNotificationHandler<OrderCreatedDomainEvent>
public class OrderStartedDomainEventHandler : IAsyncNotificationHandler<OrderStartedDomainEvent>
{ {
private readonly ILoggerFactory _logger; private readonly ILoggerFactory _logger;
private readonly IBuyerRepository<Buyer> _buyerRepository; private readonly IBuyerRepository<Buyer> _buyerRepository;
private readonly IIdentityService _identityService; 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)); _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _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; var cardTypeId = orderNotification.CardTypeId != 0 ? orderNotification.CardTypeId : 1;
@ -33,7 +33,7 @@ namespace Ordering.API.Application.DomainEventHandlers
buyer = new Buyer(buyerGuid); buyer = new Buyer(buyerGuid);
} }
var payment = buyer.AddPaymentMethod(cardTypeId,
var paymentMethod = buyer.VerifyOrAddPaymentMethod(cardTypeId,
$"Payment Method on {DateTime.UtcNow}", $"Payment Method on {DateTime.UtcNow}",
orderNotification.CardNumber, orderNotification.CardNumber,
orderNotification.CardSecurityNumber, orderNotification.CardSecurityNumber,
@ -46,7 +46,7 @@ namespace Ordering.API.Application.DomainEventHandlers
await _buyerRepository.UnitOfWork await _buyerRepository.UnitOfWork
.SaveEntitiesAsync(); .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))); .Select(i => new KeyedService("IAsyncRequestHandler", i)));
builder builder
.RegisterAssemblyTypes(typeof(OrderCreatedDomainEventHandler).GetTypeInfo().Assembly)
.RegisterAssemblyTypes(typeof(OrderStartedDomainEventHandler).GetTypeInfo().Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>))) .Where(t => t.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>)))
.AsImplementedInterfaces(); .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)); IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity));
} }
public PaymentMethod AddPaymentMethod(
public PaymentMethod VerifyOrAddPaymentMethod(
int cardTypeId, string alias, string cardNumber, int cardTypeId, string alias, string cardNumber,
string securityNumber, string cardHolderName, DateTime expiration, int orderId) string securityNumber, string cardHolderName, DateTime expiration, int orderId)
{ {
@ -33,7 +33,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
if (existingPayment != null) if (existingPayment != null)
{ {
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, existingPayment, orderId));
AddDomainEvent(new BuyerPaymentMethodVerifiedDomainEvent(this, existingPayment, orderId));
return existingPayment; return existingPayment;
} }
else else
@ -41,7 +41,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
_paymentMethods.Add(payment); _paymentMethods.Add(payment);
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, payment, orderId));
AddDomainEvent(new BuyerPaymentMethodVerifiedDomainEvent(this, payment, orderId));
return payment; 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; _orderDate = DateTime.UtcNow;
Address = address; 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() ] // 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 // DDD Patterns comment
@ -96,14 +96,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_buyerId = id; _buyerId = id;
} }
private void AddOrderCreatedDomainEvent(int cardTypeId, string cardNumber,
private void AddOrderStartedDomainEvent(int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
{ {
var orderCreatedDomainEvent = new OrderCreatedDomainEvent(
var orderStartedDomainEvent = new OrderStartedDomainEvent(
this, cardTypeId, cardNumber, cardSecurityNumber, this, cardTypeId, cardNumber, cardSecurityNumber,
cardHolderName, cardExpiration); 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 namespace Ordering.Domain.Events
{ {
public class PaymentMethodCheckedDomainEvent
public class BuyerPaymentMethodVerifiedDomainEvent
: IAsyncNotification : IAsyncNotification
{ {
public Buyer Buyer { get; private set; } public Buyer Buyer { get; private set; }
public PaymentMethod Payment { get; private set; } public PaymentMethod Payment { get; private set; }
public int OrderId { 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; Buyer = buyer;
Payment = payment; 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> /// <summary>
/// Event used when an order is created /// Event used when an order is created
/// </summary> /// </summary>
public class OrderCreatedDomainEvent
public class OrderStartedDomainEvent
: IAsyncNotification : IAsyncNotification
{ {
public int CardTypeId { get; private set; } public int CardTypeId { get; private set; }
@ -19,7 +19,7 @@ namespace Ordering.Domain.Events
public DateTime CardExpiration { get; private set; } public DateTime CardExpiration { get; private set; }
public Order Order { get; private set; } public Order Order { get; private set; }
public OrderCreatedDomainEvent(Order order,
public OrderStartedDomainEvent(Order order,
int cardTypeId, string cardNumber, int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, string cardSecurityNumber, string cardHolderName,
DateTime cardExpiration) 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 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 domainEntities = ctx.ChangeTracker.Entries<Entity>().Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any());
var domainEvents = domainEntities.SelectMany(x => x.Entity.DomainEvents).ToList(); 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(); 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; 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); var fakeBuyerItem = new Buyer(identity);
//Act //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
Assert.NotNull(result); Assert.NotNull(result);
@ -119,7 +119,7 @@ public class BuyerAggregateTest
//Act //Act
var fakeBuyer = new Buyer(Guid.NewGuid().ToString()); 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
Assert.Equal(fakeBuyer.DomainEvents.Count, expectedResult); 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 //Act
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); 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
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult); Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult);
} }
@ -153,7 +153,7 @@ public class OrderAggregateTest
var cardHolderName = "FakeName"; var cardHolderName = "FakeName";
var cardExpiration = DateTime.Now.AddYears(1); var cardExpiration = DateTime.Now.AddYears(1);
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration); 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; var expectedResult = 1;
//Act //Act


Loading…
Cancel
Save