Skip to content

Commit 603062d

Browse files
author
Anthony Sneed
committed
Use EventDriven.DDD.Abstractions v2 with MediatR.
1 parent 1c227f3 commit 603062d

File tree

85 files changed

+2634
-1345
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2634
-1345
lines changed

EventDriven.ReferenceArchitecture.sln

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "reference-architecture", "r
1515
reference-architecture\tye.yaml = reference-architecture\tye.yaml
1616
EndProjectSection
1717
EndProject
18-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventDriven.ReferenceArchitecture.Tests", "test\EventDriven.ReferenceArchitecture.Tests\EventDriven.ReferenceArchitecture.Tests.csproj", "{9809006C-2F6B-44A1-8AE2-BC449368D209}"
19-
EndProject
2018
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomerService", "reference-architecture\CustomerService\CustomerService.csproj", "{48983715-E6DF-462F-AF3C-769C1122794F}"
2119
EndProject
2220
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrderService", "reference-architecture\OrderService\OrderService.csproj", "{16A5B2CB-8C46-4F3E-B7A1-97C47D9F66E7}"
@@ -45,16 +43,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "standby", "standby", "{A045
4543
EndProject
4644
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventDriven.ReferenceArchitecture.Specs", "test\EventDriven.ReferenceArchitecture.Specs\EventDriven.ReferenceArchitecture.Specs.csproj", "{68B613B3-EB4A-41DB-A61E-1E031C5BFA85}"
4745
EndProject
46+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomerService.Tests", "test\CustomerService.Tests\CustomerService.Tests.csproj", "{C5056BF3-987B-466C-962D-77F8E725F210}"
47+
EndProject
48+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrderService.Tests", "test\OrderService.Tests\OrderService.Tests.csproj", "{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06}"
49+
EndProject
4850
Global
4951
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5052
Debug|Any CPU = Debug|Any CPU
5153
Release|Any CPU = Release|Any CPU
5254
EndGlobalSection
5355
GlobalSection(ProjectConfigurationPlatforms) = postSolution
54-
{9809006C-2F6B-44A1-8AE2-BC449368D209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55-
{9809006C-2F6B-44A1-8AE2-BC449368D209}.Debug|Any CPU.Build.0 = Debug|Any CPU
56-
{9809006C-2F6B-44A1-8AE2-BC449368D209}.Release|Any CPU.ActiveCfg = Release|Any CPU
57-
{9809006C-2F6B-44A1-8AE2-BC449368D209}.Release|Any CPU.Build.0 = Release|Any CPU
5856
{48983715-E6DF-462F-AF3C-769C1122794F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5957
{48983715-E6DF-462F-AF3C-769C1122794F}.Debug|Any CPU.Build.0 = Debug|Any CPU
6058
{48983715-E6DF-462F-AF3C-769C1122794F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -71,12 +69,19 @@ Global
7169
{68B613B3-EB4A-41DB-A61E-1E031C5BFA85}.Debug|Any CPU.Build.0 = Debug|Any CPU
7270
{68B613B3-EB4A-41DB-A61E-1E031C5BFA85}.Release|Any CPU.ActiveCfg = Release|Any CPU
7371
{68B613B3-EB4A-41DB-A61E-1E031C5BFA85}.Release|Any CPU.Build.0 = Release|Any CPU
72+
{C5056BF3-987B-466C-962D-77F8E725F210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
73+
{C5056BF3-987B-466C-962D-77F8E725F210}.Debug|Any CPU.Build.0 = Debug|Any CPU
74+
{C5056BF3-987B-466C-962D-77F8E725F210}.Release|Any CPU.ActiveCfg = Release|Any CPU
75+
{C5056BF3-987B-466C-962D-77F8E725F210}.Release|Any CPU.Build.0 = Release|Any CPU
76+
{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77+
{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06}.Debug|Any CPU.Build.0 = Debug|Any CPU
78+
{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06}.Release|Any CPU.ActiveCfg = Release|Any CPU
79+
{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06}.Release|Any CPU.Build.0 = Release|Any CPU
7480
EndGlobalSection
7581
GlobalSection(SolutionProperties) = preSolution
7682
HideSolutionNode = FALSE
7783
EndGlobalSection
7884
GlobalSection(NestedProjects) = preSolution
79-
{9809006C-2F6B-44A1-8AE2-BC449368D209} = {269CD137-4093-4100-B33E-808586D335F6}
8085
{48983715-E6DF-462F-AF3C-769C1122794F} = {C4FD0AF1-927A-4860-A634-7CE342807692}
8186
{16A5B2CB-8C46-4F3E-B7A1-97C47D9F66E7} = {C4FD0AF1-927A-4860-A634-7CE342807692}
8287
{B11B21E0-7B89-4285-990A-D98793310B02} = {C4FD0AF1-927A-4860-A634-7CE342807692}
@@ -85,6 +90,8 @@ Global
8590
{F0E48E00-7D72-4614-9C13-90A7B015B06F} = {C4FD0AF1-927A-4860-A634-7CE342807692}
8691
{A045033E-5283-4A6F-87D3-B02194595788} = {F0E48E00-7D72-4614-9C13-90A7B015B06F}
8792
{68B613B3-EB4A-41DB-A61E-1E031C5BFA85} = {269CD137-4093-4100-B33E-808586D335F6}
93+
{C5056BF3-987B-466C-962D-77F8E725F210} = {269CD137-4093-4100-B33E-808586D335F6}
94+
{B3A36227-2EB9-4BEC-8FCA-B5DB7A809C06} = {269CD137-4093-4100-B33E-808586D335F6}
8895
EndGlobalSection
8996
GlobalSection(ExtensibilityGlobals) = postSolution
9097
SolutionGuid = {427A0D03-63CA-48AE-AA95-D21800101398}

reference-architecture/CustomerService/Controllers/CustomerCommandController.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using AutoMapper;
22
using CustomerService.Domain.CustomerAggregate;
3-
using CustomerService.Domain.CustomerAggregate.CommandHandlers;
43
using CustomerService.Domain.CustomerAggregate.Commands;
54
using CustomerService.Helpers;
65
using EventDriven.DDD.Abstractions.Commands;
@@ -12,12 +11,14 @@ namespace CustomerService.Controllers
1211
[ApiController]
1312
public class CustomerCommandController : ControllerBase
1413
{
15-
private readonly CustomerCommandHandler _commandHandler;
14+
private readonly ICommandBroker _commandBroker;
1615
private readonly IMapper _mapper;
1716

18-
public CustomerCommandController(CustomerCommandHandler commandHandler, IMapper mapper)
17+
public CustomerCommandController(
18+
ICommandBroker commandBroker,
19+
IMapper mapper)
1920
{
20-
_commandHandler = commandHandler;
21+
_commandBroker = commandBroker;
2122
_mapper = mapper;
2223
}
2324

@@ -26,7 +27,7 @@ public CustomerCommandController(CustomerCommandHandler commandHandler, IMapper
2627
public async Task<IActionResult> Create([FromBody] DTO.Write.Customer customerDto)
2728
{
2829
var customerIn = _mapper.Map<Customer>(customerDto);
29-
var result = await _commandHandler.Handle(new CreateCustomer(customerIn));
30+
var result = await _commandBroker.SendAsync(new CreateCustomer(customerIn));
3031

3132
if (result.Outcome != CommandOutcome.Accepted)
3233
return result.ToActionResult();
@@ -39,7 +40,7 @@ public async Task<IActionResult> Create([FromBody] DTO.Write.Customer customerDt
3940
public async Task<IActionResult> Update([FromBody] DTO.Write.Customer customerDto)
4041
{
4142
var customerIn = _mapper.Map<Customer>(customerDto);
42-
var result = await _commandHandler.Handle(new UpdateCustomer(customerIn));
43+
var result = await _commandBroker.SendAsync(new UpdateCustomer(customerIn));
4344

4445
if (result.Outcome != CommandOutcome.Accepted)
4546
return result.ToActionResult();
@@ -52,7 +53,7 @@ public async Task<IActionResult> Update([FromBody] DTO.Write.Customer customerDt
5253
[Route("{id}")]
5354
public async Task<IActionResult> Remove([FromRoute] Guid id)
5455
{
55-
var result = await _commandHandler.Handle(new RemoveCustomer(id));
56+
var result = await _commandBroker.SendAsync(new RemoveCustomer(id));
5657
return result.Outcome != CommandOutcome.Accepted
5758
? result.ToActionResult()
5859
: new NoContentResult();

reference-architecture/CustomerService/CustomerService.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
<ItemGroup>
1010
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
11-
<PackageReference Include="EventDriven.DDD.Abstractions" Version="1.1.0" />
11+
<PackageReference Include="EventDriven.DDD.Abstractions" Version="2.0.0-beta1" />
1212
<PackageReference Include="EventDriven.DependencyInjection.URF.Mongo" Version="1.1.0" />
1313
<PackageReference Include="EventDriven.EventBus.Dapr" Version="1.2.0" />
1414
<PackageReference Include="EventDriven.EventBus.Dapr.EventCache.Mongo" Version="1.2.0" />
15-
<PackageReference Include="MongoDB.Driver" Version="2.14.1" />
16-
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
15+
<PackageReference Include="MongoDB.Driver" Version="2.15.0" />
16+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.0" />
1717
<PackageReference Include="URF.Core.Mongo" Version="6.0.1" />
1818
</ItemGroup>
1919

reference-architecture/CustomerService/Domain/CustomerAggregate/CommandHandlers/CustomerCommandHandler.cs

Lines changed: 0 additions & 88 deletions
This file was deleted.

reference-architecture/CustomerService/Domain/CustomerAggregate/Customer.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ namespace CustomerService.Domain.CustomerAggregate
88
{
99
public class Customer :
1010
Entity,
11-
ICommandProcessor<CreateCustomer, CustomerCreated>,
12-
IEventApplier<CustomerCreated>
11+
ICommandProcessor<CreateCustomer, Customer, CustomerCreated>,
12+
IEventApplier<CustomerCreated>,
13+
ICommandProcessor<UpdateCustomer, Customer, CustomerUpdated>,
14+
IEventApplier<CustomerUpdated>,
15+
ICommandProcessor<RemoveCustomer, CustomerRemoved>,
16+
IEventApplier<CustomerRemoved>
1317
{
1418
public string FirstName { get; set; } = null!;
1519
public string LastName { get; set; } = null!;
@@ -22,5 +26,24 @@ public CustomerCreated Process(CreateCustomer command)
2226
public void Apply(CustomerCreated domainEvent) =>
2327
// Set Id
2428
Id = domainEvent.EntityId != default ? domainEvent.EntityId : Guid.NewGuid();
29+
30+
public CustomerUpdated Process(UpdateCustomer command) =>
31+
// To process command, return a domain event
32+
new(command.Entity);
33+
34+
public void Apply(CustomerUpdated domainEvent)
35+
{
36+
// Set ETag
37+
if (domainEvent.EntityETag != null) ETag = domainEvent.EntityETag;
38+
}
39+
40+
public CustomerRemoved Process(RemoveCustomer command) =>
41+
// To process command, return a domain event
42+
new(command.EntityId);
43+
44+
public void Apply(CustomerRemoved domainEvent)
45+
{
46+
// Could mutate state here to implement a soft delete
47+
}
2548
}
2649
}

reference-architecture/CustomerService/Domain/CustomerAggregate/Events/CustomerCreated.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
namespace CustomerService.Domain.CustomerAggregate.Events
44
{
5-
public record CustomerCreated(Customer Customer) : DomainEvent(Customer.Id);
5+
public record CustomerCreated(Customer Entity) : DomainEvent<Customer>(Entity);
66
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using EventDriven.DDD.Abstractions.Events;
2+
3+
namespace CustomerService.Domain.CustomerAggregate.Events;
4+
5+
public record CustomerRemoved(Guid EntityId) : DomainEvent(EntityId);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using EventDriven.DDD.Abstractions.Events;
2+
3+
namespace CustomerService.Domain.CustomerAggregate.Events;
4+
5+
public record CustomerUpdated(Customer Entity) : DomainEvent<Customer>(Entity);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using CustomerService.Domain.CustomerAggregate.Commands;
2+
using CustomerService.Repositories;
3+
using EventDriven.DDD.Abstractions.Commands;
4+
5+
namespace CustomerService.Domain.CustomerAggregate.Handlers;
6+
7+
public class CreateCustomerHandler : ICommandHandler<Customer, CreateCustomer>
8+
{
9+
private readonly ICustomerRepository _repository;
10+
private readonly ILogger<CreateCustomerHandler> _logger;
11+
12+
public CreateCustomerHandler(
13+
ICustomerRepository repository,
14+
ILogger<CreateCustomerHandler> logger)
15+
{
16+
_repository = repository;
17+
_logger = logger;
18+
}
19+
20+
public async Task<CommandResult<Customer>> Handle(CreateCustomer command, CancellationToken cancellationToken)
21+
{
22+
// Process command
23+
_logger.LogInformation("Handling command: {CommandName}", nameof(CreateCustomer));
24+
var domainEvent = command.Entity.Process(command);
25+
26+
// Apply events
27+
command.Entity.Apply(domainEvent);
28+
29+
// Persist entity
30+
var entity = await _repository.AddAsync(command.Entity);
31+
if (entity == null) return new CommandResult<Customer>(CommandOutcome.InvalidCommand);
32+
return new CommandResult<Customer>(CommandOutcome.Accepted, entity);
33+
}
34+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using CustomerService.Domain.CustomerAggregate.Commands;
2+
using CustomerService.Repositories;
3+
using EventDriven.DDD.Abstractions.Commands;
4+
5+
namespace CustomerService.Domain.CustomerAggregate.Handlers;
6+
7+
public class RemoveCustomerHandler : ICommandHandler<RemoveCustomer>
8+
{
9+
private readonly ICustomerRepository _repository;
10+
private readonly ILogger<RemoveCustomerHandler> _logger;
11+
12+
public RemoveCustomerHandler(
13+
ICustomerRepository repository,
14+
ILogger<RemoveCustomerHandler> logger)
15+
{
16+
_repository = repository;
17+
_logger = logger;
18+
}
19+
20+
public async Task<CommandResult> Handle(RemoveCustomer command, CancellationToken cancellationToken)
21+
{
22+
_logger.LogInformation("Handling command: {CommandName}", nameof(RemoveCustomer));
23+
var entity = await _repository.GetAsync(command.EntityId);
24+
if (entity != null)
25+
{
26+
// Process command, apply events
27+
var domainEvent = entity.Process(command);
28+
entity.Apply(domainEvent);
29+
}
30+
31+
// Persist entity
32+
await _repository.RemoveAsync(command.EntityId);
33+
return new CommandResult<Customer>(CommandOutcome.Accepted);
34+
}
35+
}

0 commit comments

Comments
 (0)