我有一个类别实体(类),它有零或一个父类别和许多子类别 - 它是一个树结构。类别数据存储在RDBMS中,因此为了获得更好的性能,我想加载所有类别并在启动应用程序时将它们缓存在内存中。我们的系统可以有插件,我们允许插件作者访问类别树,但他们不应该修改缓存的项目和树(我认为非只读设计可能会导致这个类库中的一些细微的错误),只有系统知道何时以及如何刷新树。寻找更好的设计:只读内存缓存机制
下面是一些演示代码:
public interface ITreeNode<T>
where T : ITreeNode<T>
{
// No setter
T Parent { get; }
IEnumerable<T> ChildNodes { get; }
}
// This class is generated by O/R Mapping tool (e.g. Entity Framework)
public class Category : EntityObject
{
public string Name { get; set; }
}
// Because Category is not stateless, so I create a cleaner view class for Category.
// And this class is the Node Type of the Category Tree
public class CategoryView : ITreeNode<CategoryView>
{
public string Name { get; private set; }
#region ITreeNode Memebers
public CategoryView Parent { get; private set; }
private List<CategoryView> _childNodes;
public IEnumerable<CategoryView> ChildNodes {
return _childNodes;
}
#endregion
public static CategoryView CreateFrom(Category category) {
// here I can set the CategoryView.Name property
}
}
到目前为止好。 但是,我想让ITreeNode接口可重复使用,对于其他一些类型,树不应只读。我们无法与上述只读ITreeNode要做到这一点,所以我想ITreeNode是这样的:
public interface ITreeNode<T> {
// has setter
T Parent { get; set; }
// use ICollection<T> instead of IEnumerable<T>
ICollection<T> ChildNodes { get; }
}
但是,如果我们做ITreeNode写,那么我们不能使分类树只读,这是不好。
所以我觉得,如果我们可以这样做:
public interface ITreeNode<T> {
T Parent { get; }
IEnumerable<T> ChildNodes { get; }
}
public interface IWritableTreeNode<T> : ITreeNode<T> {
new T Parent { get; set; }
new ICollection<T> ChildNodes { get; }
}
这是好事还是坏事?有更好的设计吗?非常感谢! :)
感谢。类别树应该是只读的,但在一些其他的例子中,例如,一个自定义的asp.net树控件,控制用户应该能够从树中添加/删除节点,所以树不应该是只读的。根据你的回答,我认为我们可以这样做: (1)使ITreeNode只读,也就是说,没有父节点的setter,并为ChildNodes返回IEnumerable。 (2)对于Category Tree,我们使Category类实现ITreeNode,就像您在示例中所做的那样。(3)对于Tree Control,我们使用“new”关键字来隐藏ChildNodes属性,并让ChildNodes返回一个非只读集合。 对不对? –
2010-05-14 04:01:11
@Dylan Lin - 是的,那可行。但是在Tree Control上,您应该让ChildNodes返回IEnumerable,以便您可以根据实现控制对集合的访问。 –
2010-05-14 14:41:26
我明白了。非常感谢。 – 2010-05-15 13:21:08