Code snippets from GregYoung 8 CQRS Class

March 16th, 2019

Code snippets from GregYoung 8 CQRS Class - YouTube

public class DeactivateInventoryItemCommand {

public readonly Guid InventoryItemId;

public readonly string Comment;

 

public DeactivateInventoryItemCommand (Guid id, string comment) {

InventoryItemId = id;

Comment = comment;

}

void DeactivateInventoryItem(Guid, string comment)

 

 

CommandHandler

contains no logic, logic is in domain object

delegates to domain object

public class DeactivateInventoryItemHandler : Handles<DeactivateInventoryItem> {

public DeactivateInventoryItemHandler(InventoryItemRepository rep){}

 

void Handle(DeactivateInventoryItem cmd) {

var item = repository.GetById(cmd.Id);

item.Deactivate(cmd.Comment);

}

}

 

 

 

Application Services

cross-cutting concerns (logging, authentication)

public class TransactionalHandler<T> : Handles<T> where T:Message {

private Handles<T> next;

public TransactionalHandler(Handles<T> Next) {

next = Next;

}

 

public Handle(T cmd) {

using(new UnitOfWork()) {

next.Handle(cmd);

}

}

}

 

public class LoggingHandler<T> : Handles<T> where T:Message {

private Handles<T> next;

public TransactionalHandler(Handles<T> Next) {

next = Next;

}

 

 

public Handle(T cmd) {

using(new UnitOfWork()) {

next.Handle(cmd);

}

}

}

 

 

var handler = new TransactionalHandler<DeactiveateInventoryItemCommand>(

new LoggingHandler<DeactiveateInventoryItemCommand>(

new DeactiveateInventoryItemHandler()))

 

 

CommandHandler only 1

[RequiresPermission("Admin")]

[Transactional]

[LogsTo("C:\\foo.txt")]

public class DeactivateInventoryItemHandler : Handles<DeactivateInventoryItem> {

public DeactivateInventoryItemHandler(InventoryItemRepository rep){}

 

void Handle(DeactivateInventoryItem cmd) {

var item = repository.GetById(cmd.Id);

item.Deactivate(cmd.Comment);

}

}

 

 

command and event

public class DeactivateInventoryItem {

public readonly Guid InventoryItemId;

public readonly string Comment;

 

 

public DeactivateInventoryItemCommand (Guid id, string comment) {

InventoryItemId = id;

Comment = comment;

}

 

public class InventoryItemDeactivated {

public readonly Guid InventoryItemId;

public readonly string Comment;

 

public InventoryItemDeactivated (Guid id, string comment) {

InventoryItemId = id;

Comment = comment;

}

 

 

EventHandler

[Transactional]

public class DeactivatedEventHandler : Handles <InventoryItemDeactivatedEvent> {

public void Handle(InventoryItemDeactivatedEvent e) {

INSERT INTO FOO () VALUES e.cjjd e.ccc

}

}

 

 

AggregateRoot

public class InventoryItem : AggregateRoot {

WarehouseLocationInformation info;

bool activated;

 

public InventoryItem() {

RegisterHandler(typeof(DeactivatedEvent), ApplyDeactivatedEvent);

RegisterHandler(typeof(WarehouseLocationInformationRegistered), ApplyWareh...Registered);

}

 

private void Apply(DeactivatedEvent e) {

activated = false;

}

 

private void Apply(WarehouseLocationInformationRegistered e) {

info =  new WarehouseLocationInformation(e.PhysicalLocation, e.GeoLocation, e.PaymentRate);

}

 

private void Deactivate() {

if(!activated) throw new InvalidOperationException();

if(comment==null) throw ...();

ApplyEvent(new InventoryDeactivatedEvent(id));

}

}

 

 

public class AggregateRoot : IAggregateRoot {

private Dictionary<Type, appliesEvent> lookup = new Dictionary<Type, appliesEvent>();

 

protected void RegisterHandler<T>(appliesEvent handler) {

lookup.add(typeof(T), handler);

}

 

public IEnumerable<Event> GetChanges() {

foreach(Event e in events) yield return e;

events.Clear();

}

 

protected void ApplyEvent(Event e) { ApplyEvent(e, true); }

 

private void ApplyEvent(Event e, bool add) {

appliesEvent handler;

if(!lookup.TryGetValue(e.getType(), out handler)) {

throw new HandlerNotFoundException();

}

handler(e);

if(add) UnitOfWork.GetCurrent().Enregister(e);

}

 

public void LoadFromHistory(IEnumerable<Event> events) {

foreach(Event e in events) {

ApplyEvent(e, false);

}

}

}

 

 

InventoryItemDeactivatedEvent

public class InventoryItemDeactivatedEvent : Event {

public readonly Guid Id;

public InventoryItemDeactivatedEvent (Guid id) {

Id = id;

}

 

 

 

Test

[TestFixture]

public class when_an_inventory_item_is_deactivated : AggregateRootTestFixture<InventoryItem> {

private Guid id = Guid.newGuid();

 

protected override IEnumerable<Event> Given() {

yield return New.InventoryItemCreated.WithName("Test");

}

 

protected override void When() {

sut.Deactivate();

}

 

[Test]

public void should_publish_deactivated_Event() {

Assert.Inconclusive();

}

 

[Test]

public void should_publish_event_with_correct_id() {

Assert.AreEquel(id, ((InventoryDeactivatedEvent) events[0]).AggregateId);

}

}

 

public abstract class AggregateRootTestFixture<T> : where T:IAggregateRoot, new() {

protected IAggregateRoot root;

protected Exception caught = null;

protected T sut;

protected List<Event> events;

 

protected abstract IEnumerable<Event> Given();

protected abstract void When();

 

[SetUp]

public void Setup() {

root = new T();

root.LoadFromHistory(Given());

try{

When();

events = new List<Event>(root.GetChanges());

} catch(Exception Ex) {

caught = Ex;

}

}

}

 

bdd

Given a set of events

when I issue a command

expect a set of events

 

Given

an inventory item created

When I

deactivate inventory item

expect

inventory item deactivated

 

Given

an inventory item created

an inventory item deactivated

When I

deactivate inventory item

expect

invalidoperation exception

 

 

 

View

public class InventoryCountView : Handles<InventoryAddedEvent>, Handles<InventoryItemRemovedEvent>, Handles<InventoryItemCreatedEvent>

public void Handle(InventoryItemAddedEvent) {

update InventoryCountView set currentcount = currentcount + e.Count

}

 

public void Handle(InventoryItemCreatedEvent e) {

insert into InventoryCountView currentcount values 0

}

 

 

 

 

Versioning

public class InventoryItemDeactivatedEvent : Event {

public readonly Guid Id;

public InventoryItemDeactivatedEvent (Guid id) {

Id = id;

}

}

 

public class InventoryItemDeactivatedEvent_v2 : Event {

public readonly Guid Id;

public readonly string Comment;

public InventoryItemDeactivatedEvent (Guid id, string comment) {

Id = id;

Comment = commment;

}

}

 

public classInventoryItemDeactivatedEvent_v3 : Event {

 

 

T ConvertTo<T,V>(V v) where T:Message, V:Message

 

 

DeactivatedEvent_v2 ConvertTo(DeactivatedEvent v) {

return new DeactivatedEvent_v2(v.Id, null);

}