2010-05-12 81 views
3

我有一個類別實體(類),它有零或一個父類別和許多子類別 - 它是一個樹結構。類別數據存儲在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; } 
} 

這是好事還是壞事?有更好的設計嗎?非常感謝! :)

回答

1

有一兩件事你可以嘗試是使用列表<牛逼>爲您要爲只讀的IEnumerable的項目。然後,當您填充樹結構時,您可以在內部調用您的列表上的AsReadOnly()方法,該方法將返回ReadOnlyCollection <T>並且您的數據的使用者將無法修改集合的內容。

這種方法並不只讀但從接口的點,而是試圖調用像的方法添加的收集將失敗,並拋出一個異常。

爲了保護您的其他成員,您可以在類的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; 
     } 
    } 
} 
+0

感謝。類別樹應該是隻讀的,但在一些其他的例子中,例如,一個自定義的asp.net樹控件,控制用戶應該能夠從樹中添加/刪除節點,所以樹不應該是隻讀的。根據你的回答,我認爲我們可以這樣做: (1)使ITreeNode只讀,也就是說,沒有父節點的setter,併爲ChildNodes返回IEnumerable 。 (2)對於Category Tree,我們使Category類實現ITreeNode,就像您在示例中所做的那樣。(3)對於Tree Control,我們使用「new」關鍵字來隱藏ChildNodes屬性,並讓ChildNodes返回一個非只讀集合。 對不對? – 2010-05-14 04:01:11

+0

@Dylan Lin - 是的,那可行。但是在Tree Control上,您應該讓ChildNodes返回IEnumerable ,以便您可以根據實現控制對集合的訪問。 – 2010-05-14 14:41:26

+0

我明白了。非常感謝。 – 2010-05-15 13:21:08