I agree with Mauro too !
I would also move the factory function inside the aggregate in order to enforce the invariant by aggregate itself.
var expense = repo.get(id);
expense.CreateLineItems(command.LineItems)
.Submit();
repo.save(expense);
public class Expense {
private int CustomerDiscount {get;set;}
private int PromoDiscount {get;set;}
public void CreateLineItems(List<ExpenseItem> items) {
items.forEach(i=>CreateLineItem);
return this;
}
public void Submit() {
// put submit logic
//Event.Add(ExpeseSubmitted);
}
/*
This arrangement makes it practical to enforce all invariants for objects
in the AGGREGATE and for the AGGREGATE as a whole in any state change.
*/
public void CreateLineItem(ExpenseItem item)
{
// aggregate can inforce invariants here
// asertionConcerns.AssertNull(item,'line item can not be null') //etc.
var item = new LineItem
{
Quantity = item.Quantity,
ExpnseLineItemId = item.Id,
UnitPrice = item.amount,
UnitPriceDiscount = CustomerDiscount + PromoDiscount // give the aggregate opportunity to add current state values
};
/* Here you can also add events into your event collection which can be published once expese is persisted in db later.
Events.Add(ExpenseLineItemCreatedEvent)
*/
LineItems.Add(item);
}
}