Я использую составной шаблон, как показано на диаграмме классов ниже. По сути, мой основной лист (распределение) имеет одно свойство, продолжительность, которое я хочу накапливать в различных составных частях.
Я также хочу иметь подсчет распределений и возможность возвращать распределения в виде коллекции, которую я могу использовать для привязки данных в презентациях.
Этот вопрос касается реализации С#, в частности:
- Здесь есть интересный пост a>, у которого есть расширение, позволяющее делать это рекурсивно, а также альтернативный подход, полностью избегающий рекурсии. Есть ли у вас общий способ получить распределение так, как это делаю я? Я еще не решил, кажется ли код, который я написал, неудобным, потому что мне не нравится шаблон, или он неудобен!
- Видите ли вы здесь какие-либо простые возможности для кэширования результатов первой итерации и тем самым минимизации дальнейших итераций?
С уважением,
Беррил
Код в классе Composite
public class AllocationComposite : AllocationNode
{
protected readonly IList<AllocationNode> _children;
public AllocationComposite() { _children = new List<AllocationNode>(); }
#region Implementation of AllocationNode
public override void Adopt(AllocationNode node) ...
public override void Adopt(IEnumerable<AllocationNode> nodes)...
public override void Orphan(AllocationNode node)...
public override void Orphan(IEnumerable<AllocationNode> nodes)...
public override IEnumerable<AllocationNode> Descendants
{
get
{
return _children.Concat(_children.SelectMany(child => child.Descendants));
}
}
public override IEnumerable<Allocation> Allocations
{
get
{
return Descendants.OfType<Allocation>();
}
}
public override TimeSpan Duration {
get {
return Allocations.Aggregate(TimeSpan.Zero, (current, child) => current + child.Duration);
}
}
public override int Count { get { return Allocations.Count(); } }
#endregion
public override string ToString() {
return String.Format("{0} for {1}",
"allocation".PluralizeWithCount(Count),
"hour".PluralizeWithCount(Duration.TotalHours, "F2"));
}
}
}
Реализация по умолчанию в абстрактном компоненте
public abstract class AllocationNode: Entity, IAllocationNode
{
#region Implementation of AllocationNode
public virtual TimeSpan Duration { get { return TimeSpan.Zero; } set { } }
public virtual void Adopt(AllocationNode node) { throw new InvalidOperationException(...)); }
public virtual void Adopt(IEnumerable<AllocationNode> nodes) { throw new InvalidOperationException(...)); }
public virtual void Orphan(AllocationNode node) { throw new InvalidOperationException(...)); }
public virtual void Orphan(IEnumerable<AllocationNode> nodes) { throw new InvalidOperationException(...)); }
public virtual int Count { get { return 1; } }
public virtual IEnumerable<AllocationNode> Descendants { get { return Enumerable.Empty<AllocationNode>(); } }
public virtual IEnumerable<Allocation> Allocations { get { return Enumerable.Empty<Allocation>(); } }
#endregion
}