首页 文章

寻找更好的设计:只读内存缓存机制

提问于
浏览
3

我有一个Category实体(类),它有零个或一个父类别和许多子类别 - 它是一个树结构 . Category数据存储在RDBMS中,所以 for better performance, I want to load all categories and cache them in memory while launching the applicaiton.

我们的系统可以有插件,我们允许插件作者访问类别树,但是他们不应该修改缓存的项目和树(我认为非读取设计可能会导致这种情况下的一些微妙的错误),只有系统知道何时以及如何刷新树 .

以下是一些演示代码:

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
    }
}

到现在为止还挺好 . However, I want to make ITreeNode interface reuseable, and for some other types, the tree should not be readonly . 我们无法使用上面的只读ITreeNode执行此操作,因此我希望ITreeNode如下所示:

public interface ITreeNode<T> {
    // has setter
    T Parent { get; set; }
    // use ICollection<T> instead of IEnumerable<T>
    ICollection<T> ChildNodes { get; }
}

But if we make the ITreeNode writable, then we cannot make the Category Tree readonly ,这不好 .

所以我想如果我们能这样做:

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; }
}

Is this good or bad? Are there some better designs? Thanks a lot! :)

1 回答

  • 1

    您可以尝试的一件事是将 List<T> 用于您想要只读的IEnumerable项目 . 然后,当您填充树结构时,您可以在内部调用列表中的 AsReadOnly() 方法,该方法将返回 ReadOnlyCollection<T> ,并且您的数据的使用者将无法修改集合的内容 .

    从接口的角度来看,这种方法不是 ReadOnly ,但尝试在集合上调用类似 Add 的方法会失败并抛出异常 .

    为了保护您的其他成员,可以在类中的ITreeNode的实现类中构建一些私有只读标志,然后将您的标志设置为在缓存项目上只读 .

    这样的东西......


    public class TreeNode : ITreeNode
    {
        private bool _isReadOnly;
        private List<ITreeNode> _childNodes = new List<ITreeNode>();
    
        public TreeNode Parent { get; private set; }
    
        public IEnumerable<ITreeNode> ChildNodes
        {
            get
            {
                return _isReadOnly ? _childNodes.AsReadOnly() : _childNodes;
            }
        }
    }
    

相关问题