Sto costruendo un'applicazione web con C # e ho una radice aggregata che ha diverse entità e oggetti valore. Poi ho un oggetto repository che mantiene l'aggregazione nel database (sto usando ADO.NET come il mio livello di persistenza dell'infrastruttura).
L'aggregato ha anche diversi eventi collegati ai suoi metodi, in modo che altre azioni possano essere eseguite al di fuori dell'aggregato (ad esempio, il metodo OpenRequisition di un aggregato Cliente attiva l'evento RequisitionCreatedEvent, e un gestore quindi accoda un'azione per aggiornare le statistiche per quanto riguarda il cliente.
Questo è un esempio semplificato.
class Customer {
private Guid _id;
private string _shortName;
private string _legalName;
private TaxCode _taxCode;
private ContactInfo _primaryContact;
private List<Requisitions> _requisitions; //Requisition is an entity
private IDomainEvents _events;
// and so many other fields
public Requisition OpenRequisition(RequisitionDefinition definition, User requestedBy)
{
Requisition req = ... // create the new requisition somehow
_requisitions.Add(req);
_events.Invoke(new RequisitionCreatedEvent(this, req));
return req;
}
// and so on
}
Il problema che sto affrontando non è su come persistere, ma su come ricostruire l'oggetto aggregato dal database. Molti dei campi del cliente hanno setter, come ShortName o LegalName, o anche TaxCode. Altri no, come il campo _requisiti. Non ho un modo diretto per ricostruire le richieste esistenti. Se espongo le richieste in qualche modo (come proprietà List), allora potrei fare qualcosa di simile nel mio repository:
var requisitions = ... // get requisitions for this customer
var customer = new Customer(id);
customer.Requisitions.AddRange(requisitions);
Ma poi altrove si potrebbe fare:
customer.Requisitions.Add(new Requisition());
aggirando la logica e le convalide impostate nel metodo OpenRequisition. D'altra parte, se invoco il metodo OpenRequisition dal mio repository, il gestore di eventi verrà chiamato ogni volta, e non dovrebbe, perché sto ricostruendo l'oggetto dal database, non aprendo effettivamente una nuova richiesta.
Quello che ho finora, è quello di creare un costruttore e quindi passare tutti questi parametri, qualcosa del genere:
public Customer(IDomainEvents events, Guid id, IEnumerable<Requisition> requisitions, ... and so on)
{
... // perform validations
_events = events;
_id = id;
_requisitions = new List<Requisition>(requisitions);
... // and so on
}
Tuttavia, questo aggregato ha molti altri nodi figli, quindi il costruttore sta crescendo e crescendo, e non sembra giusto. A un certo punto ho cercato di creare una classe factory, ma ho ancora bisogno del grande costruttore, o qualcosa come avere setter interni anche per _events e _requisitions, e non sembra ancora giusto.
Quindi, la mia domanda è: come ricostruire complesse radici aggregate, come passare tutti i parametri necessari all'aggregato per continuare a funzionare senza che l'oggetto esegua il lavoro già fatto (come l'attivazione del gestore di eventi). Altrimenti, quali opzioni considereresti su scenari come questo?