Aggregates represent the business models explicitly. They are designed to fully match any needed requirements. Any change done to an instance of an aggregate goes through the aggregate root.
Aggregate root
Creating an aggregate root with Cronus is as simple as writing a class that inheritsAggregateRoot<TState> and a class for the state of the aggregate root. To publish an event from an aggregate root use the Apply(IEvent @event) method provided by the base class.
publicclassConcert:AggregateRoot<ConcertState>{Concert(){}// keep the private parameterless constructorpublicConcert(stringname,Venuevenue,DateTimeOffsetstartTime,TimeSpanduration){ // business logic for creating a concertApply(newConcertAnnounced(...));}publicvoidRegisterPerformer(Performerperformer){ // business logic for registering a performerApply(newPerformerRegistered(...));} // ...}
Aggregate root state
The aggregate root state keeps the current data of the aggregate root and is responsible for changing it based on events raised only by the root.
Use the abstract helper class AggregateRootState<TAggregateRoot, TAggregateRootId> to create an aggregate root state. It can be accessed in the aggregate root using the state field provided by the base class. Also, you can implement the IAggregateRootState interface by yourself in case inheritance is not a viable option.
To change the state of an aggregate root, create event-handler methods for each event with a method signature public void When(Event e) { ... }.
You could read more about the state pattern here and here.
Aggregate root id
All aggregate root ids must implement the IAggregateRootId interface. Since Cronus uses URNs for ids that will require implementing the URN specification as well. If you don't want to do that, you can use the provided helper base class AggregateRootId.
Another option is to use the AggregateRootId<T> class. This will give you more flexibility in constructing instances of the id. Also, parsing URNs will return the specified type T instead of AggregateUrn.
public class ConcertState : AggregateRootState<Concert, ConcertId>
{
public ConcertState()
{
Performers = new List<Performer>();
}
public override ConcertId Id { get; set; }
public string Name { get; private set; }
public Venue Venue { get; private set; }
public DateTimeOffset StartTime { get; private set; }
public TimeSpan Duration { get; private set; }
public List<Performer> Performers { get; private set; }
public void When(ConcertAnnounced @event)
{
// change the state here ...
}
public void When(PerformerRegistered @event)
{
// change the state here ...
}
}
[DataContract(Name = "e96d90d0-4943-43f4-8a84-cd90b1217d06")]
public class ConcertId : AggregateRootId
{
const string RootName = "concert";
public ConcertId(AggregateUrn urn) : base(RootName, urn) { }
public ConcertId(string idBase, string tenant) : base(idBase, RootName, tenant) { }
protected ConcertId() { }
}