You can avoid that with this pattern:
//your aggregate
public void DoSomething(DateTime startDate, DateTime endDate)
{
ApplyChange(TripDefinition.For(startDate, endDate));
}
void Apply(SomethingHappened e)
{
var tripDefinition = new TripDefinition(this.ApplyChange);
tripDefinition.ApplyChange(e);
tripDefinitions.Add(tripDefinition);
}
void Apply(SomethingElseHappened e)
{
tripDefinitions[e.Id].ApplyChange(e);
}
public class TripDefinition
{
public static SomethingHappened For(DateTime startDate, DateTime endDate)
{
if (endDate < startDate)
{
throw new InvalidOperationException();
}
return new SomethingHappened{...};
}
public TripDefinition(Action<Event> apply)
{
_apply = apply;
}
public void SomeOtherBehavior()
{
_apply(new SomethingElseHappened(...));
}
public void ApplyChange(Event e)
{
// reflection magic thing
}
void Apply(SomethingHappened e)
{
_startDate = e.StartDate;
_endDate = e.EndDate;
}
void Apply(SomethingElseHappened e)
{
_someOtherState = e.SomeOtherState;
}
}
It's a bit weird that an event is returned from a static method on your entity but eh, it works. That being said, I would use a value object containing startDate / endDate to do that validation.