下面是使用复合模式的第一次尝试。复合迭代失败(.net)
它的工作原理是,我可以随意嵌套并获得Duration属性的正确结果,并且是合成的焦点。但在一个编码问题迭代超过所需输出复合的ToString()孩子失败:
System.InvalidOperationException : Collection was modified; enumeration operation may not execute.
的是在这个posting GetDescendents一些扩展方法,包括使用堆栈,以避免一个花费递归和嵌套迭代器。
我想了解的图案最好先的,所以我有几个问题在这里:
- 我怎样才能改变现有的重复代码,以防止这种错误?我知道如何将它转换为Linq等价物,但我想把它作为循环直到我明白它有什么问题。
- 在Composite中提供Count属性还是以某种方式缓存迭代后的计数是典型的?
- 在您不需要专门收藏的一般情况下,您通常会将您的Children属性设置为IEnumerable,IList还是List?
任何工作(非trival).net代码示例的良好链接也将非常感激。
干杯,
Berryl
CODE
public interface IComponent {
void Adopt(IComponent node);
void Orphan(IComponent node);
TimeSpan Duration { get; }
IEnumerable<IComponent> Children { get; }
}
public class Allocation : Entity, IAllocationNode {
public void Adopt(IAllocationNode node) { throw new InvalidOperationException(_getExceptionMessage("Adopt", this, node)); }
public void Orphan(IAllocationNode node) { throw new InvalidOperationException(_getExceptionMessage("Orphan", this, node)); }
public IEnumerable<IAllocationNode> Allocations { get { return Enumerable.Empty<IAllocationNode>(); } }
public virtual TimeSpan Duration { get; set; }
}
class MyCompositeClass : IAllocationNode {
public MyCompositeClass() { _children = new List<IAllocationNode>(); }
public void Adopt(IAllocationNode node) { _children.Add(node); }
public void Orphan(IAllocationNode node) { _children.Remove(node); }
public TimeSpan Duration {
get {
return _children.Aggregate(TimeSpan.Zero, (current, child) => current + child.Duration);
}
}
public IEnumerable<IAllocationNode> Children {
get {
var result = _children;
foreach (var child in _children) {
var childOnes = child.Children;
foreach (var node in childOnes) {
result.Add(node);
}
}
return result;
}
}
private readonly IList<IAllocationNode> _children;
#endregion
public override string ToString() {
var count = Children.Count();
var hours = Duration.TotalHours.ToString("F2");
return string.Format("{0} allocations for {1} hours", count, hours);
}
}
@Ari。是的,这解决了它。我没有看到我限制遍历的深度 - 你将如何修改这个以获得所有的后代? – Berryl 2011-03-20 15:13:52
拼写错了你的名字,对不起。我没有看到我在限制遍历的深度 - 你会如何修改这个以获得所有的后代?干杯 – Berryl 2011-03-20 15:20:22
@Berryl:你说得对;我已经进行了编辑。 – Ani 2011-03-20 15:21:38