class Delivery {
Dictionary<Type, Func<ScheduleDto, ScheduleEntity>> ScheduleFactories =
new Dictionary<Type, Func<ScheduleDto, ScheduleEntity>> {
{ typeof(DailyScheduleDto), GetDailySchedule},
{ typeof(HourlyScheduleDto), GetHourlySchedule}
};
public Guid Id { get; private set; }
public string Description { get; private set; }
public StatusEnum Status { get private set; }
public Schedule { get; private set; }
public Delivery(DeliveryDto dto){
Id = dto.Id;
Description = dto.Description;
Status = StatusEnum.New;
Schedule = ScheduleFactories[dto.Schedule.GetType()](dto.Schedule);
}
public void Update(DeliveryDto dto){
Description = dto.Description;
Schedule.Update(dto.Schedule);
}
public DateTime GetNextDeliverySchedule(DateTime after){
return Schedule.GetNextDeliverySchedule(after);
}
public enum StatusEnum { New, InProgress, Complete }
Schedule GetDailyScheduleEntity(ScheduleDto dto){
return new DailyScheduleEntity((DailyScheduleDto)dto);
}
Schedule GetHourlyScheduleEntity(ScheduleDto dto){
return new HourlyScheduleEntity((HourlyScheduleDto)dto);
}
}
abstract class Schedule {
public DateTime StartsOn { get; private set; }
public abstract DateTime GetNextDeliverySchedule(DateTime after);
public virtual void Update(ScheduleDto dto){
StartsOn = dto.StartsOn;
}
public Schedule(ScheduleDto dto) {
StartsOn = dto.StartsOn;
}
}
class DailySchedule : Schedule {
public DaysEnum Days { get; private set; }
public override DateTime GetNextDeliverySchedule(DateTime after){
return // logic for calculating the next day based on Days;
}
public DailySchedule(DailyScheduleDto dto)
: base(dto)
{
Days = dto.Days.ToEnum<DaysEnum>();
base.Update(dto);
}
public override void Update(ScheduleDto dto){
Days = ((DailyScheduleDto)dto).Days.ToEnum<DaysEnum>();
}
[Flags]
public enum DaysEnum{
Monday, Tuesday, Wednesday, Thursday, Friday
}
}
class HourlySchedule : Schedule {
public int Interval { get; private set }
public override DateTime GetNextDeliverySchedule(DateTime after){
return // logic for calculating the next hour based on interval;
}
public HourlySchedule(HourlyScheduleDto dto)
: base(dto)
{
Interval = dto.Interval;
}
public override void Update(ScheduleDto dto){
Days = ((HoulryScheduleDto)dto).Interval;
base.Update(dto);
}
}
class DeliveryService : IDeliveryService {
public void Add(DeliveryDto dto){
var delivery = new Delivery(dto);
unitOfWork.Add<Delivery>(delivery);
unitOfWork.SaveChanges();
}
public void Update(DeliveryDto dto){
var delivery = unitOfWork.Get<Delivery>(dto.Id);
delivery.Update(dto);
unitOfWork.SaveChanges();
}
}
DeliveryDto{
Guid Id {get; set;}
string Description {get; set;}
ScheduleDto Schedule {get; set;}
}
ScheduleDto{
DateTime StartsOn {get; set;}
}
HourlyScheduleDto : ScheduleDto{
int Interval {get; set;}
}
DailyScheduleDto : ScheduleDto{
String Days {get; set;}
}
@AlexeyThanks for your comments, but could you elaborate a little please. If base logic has to diverge than I think that woiuld signal that the logic is no longer common to all derived types, meaning logic can be moved to the override in the derived types. If logic is still common among some derived types and not others; the common logic can be centralized in a helper. So I don't see that this would break compatibility.
--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
namespace RicardoDeSilva{namespace Contracts{public enum ScheduleGeneratorType { Daily, Hourly /*, Add others */ };public class DeliveryDetails{public string Id { get; protected set; }public string Description { get; protected set; }public DateTime? DeliverStartingFrom { get; protected set; }public ScheduleGeneratorType ScheduleGenerator { get; protected set; }}}namespace Modules{using Contracts;public interface IGenerateSchedules{IEnumerable<DateTime> StartingFrom(DateTime startDate);}public static class ScheduleModule{public static IGenerateSchedules GetGenerator(ScheduleGeneratorType @type){switch (@type){case (ScheduleGeneratorType.Daily): return new DailyScheduleGenerator();case (ScheduleGeneratorType.Hourly): return new HourlyScheduleGenerator();default: return UnknownScheduleGenerator;}}class HourlyScheduleGenerator : IGenerateSchedules{IEnumerable<DateTime> IGenerateSchedules.StartingFrom(DateTime startDate){var currentDate = startDate;while (true){// this will probably be way more complicatedif (currentDate.TimeOfDay.TotalHours >= 8.5 &¤tDate.TimeOfDay.TotalHours < 17){yield return currentDate;}currentDate += TimeSpan.FromHours(1);}}}class DailyScheduleGenerator : IGenerateSchedules{IEnumerable<DateTime> IGenerateSchedules.StartingFrom(DateTime startDate){var currentDate = startDate;while (true){// this will probably be way more complicatedif (currentDate.DayOfWeek != DayOfWeek.Saturday &¤tDate.DayOfWeek != DayOfWeek.Sunday){yield return currentDate;}currentDate += TimeSpan.FromDays(1);}}}class NopScheduleGeneratorClass : IGenerateSchedules{IEnumerable<DateTime> IGenerateSchedules.StartingFrom(DateTime startDate){throw new NotImplementedException();}}public static IGenerateSchedules UnknownScheduleGenerator = new NopScheduleGeneratorClass();}}namespace Domain{using Contracts;using Modules;public class Delivery{void ProvisionDelivery(DeliveryDetails deliveryDetails){var generateSchedule = ScheduleModule.GetGenerator(deliveryDetails.ScheduleGenerator);Guard.Against(generateSchedule == ScheduleModule.UnknownScheduleGenerator, "Unknown schedule generator");// a later starting date might be picked for whatever reason (f.e. not in stock etc)var earliestDate = deliveryDetails.DeliverStartingFrom.HasValue ? deliveryDetails.DeliverStartingFrom.Value : DateTime.Now;// here other dates might be picked (f.e. national holiday)var scheduledDate = generateSchedule.StartingFrom(earliestDate).First();// everything is ok, persistthis.DeliveryWasProvisioned(deliveryDetails.Id, deliveryDetails.Description, scheduledDate);}private void DeliveryWasProvisioned(string Id, string Description, DateTime scheduledDate){// TODOthrow new NotImplementedException();}}}public static class Guard{public static void Against(bool condition, string message){if (condition){throw new InvalidOperationException(message);}}public static void That(bool condition, string message){Guard.Against(!condition, message);}}}
--