Working with Polymorphic child Entities

"[email protected] [domaindrivendesign]" <[email protected]> 25 May 2015 23:53:58 -0700
Newsgroups gmane.comp.programming.domain-driven-design
Message-ID <[email protected]>
I have been thinking of the best approach to deal with Aggregate Entities having polymorphic children and wonder if anyone has comments on whether the following implementation is correct or whether I may be overlooking some potential pitfalls.
 

 The following code demonstrates a system for sending some sort of communication on varying schedules. User will typically create a Delivery with a message and assign one of two types of Schedule, Hourly' or 'Weekly'. A Windows Service will periodically poll the Data Store to identify Deliveries ready top be sent 
 

 THE DOMAIN
 

 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 Message { get; private set; }
    public StatusEnum Status { get private set; }
    public Schedule { get; private set; }
    public Delivery(DeliveryDto dto){
        Id = dto.Id;
        Message = dto.Message
        Status = StatusEnum.New;
        Schedule = ScheduleFactories[dto. Schedule.GetType()](dto. Schedule);
    }
    public void Update(DeliveryDto dto){
        Message = dto.Message;
        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();
     }
}  
 CONTRACTS
 
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;}
}  
 I would typically have specific dtos for creating new instances and performing updates, but reuse the same types here for simplicity.
 

 
 Although there is an argument that passing Dtos directly to Entities would tightly couple clients to the domain, my intention is to provide a thin facade-type layer that would be responsible for 'upgrading' dtos to maintain compatibility with existing clients should the current dto's need to change to accommodate changing business needs