Lightweight library with support for commands, domain events and aggregates.
Let´s have a look at the basic concepts.
// An aggregate root
public class MyAggregateRoot : AggregateRoot
{
public string Value{get; set;}
public void ApplyValue(string value)
{
this.Value = value;
// emit a domain event
EmitEvent(new ValueApplied{ Value = value });
}
}
Commands can be decorated with DataAnnotations and will be validated by this library when executed.
// A command
public class ApplyValue : Command<MyAggregateRoot>
{
[Required]
public string Value { get; set;}
}
// An event
public class ValueApplied : Event
{
public string Value { get; set;}
public override string Stream => "MyAggregateRoot";
}
The thought behind this library is that we have one eventstream per aggregate. To avoid having to specify the stream on each event, we can create a base class for each aggregate and seal the Stream property.
public abstract class MyAggregateRootEvent : Event
{
public override sealed string Stream => "MyAggregateRoot";
}
public class ValueApplied : MyAggregateRootEvent
{
public string Value { get; set;}
}
Event handlers will register automatically and append the event to the stream specified in the Event. To publish the event the Event handler will use any class that inherits the EventStreamProvider class available in this library.
// an eventhandler for the event above
public class ValueAppliedEventHandler : DomainEventHandler<ValueApplied>
{
// default behaviour is to publish the event on the stream.
// if required this method can be overridden here
// public override void HandleEvent(Event evt){}
}
public class ApplyValueCommandHandler : CommandHandler<MyAggregateRoot, ApplyValue>
{
protected override void ExecuteCommand(MyAggregateRoot aggregateRoot, ApplyValue command)
{
aggregateRoot.ApplyValue(command.Value);
}
}