2010-05-12 2 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

한 가지 목록 < T는 읽기 전용하려는 IEnumerable을 항목에 대한 >을 사용하는 것입니다. 그런 다음 트리 구조를 채울 때 AsReadOnly() 메서드를 호출하여 ReadOnlyCollection <T>을 반환 할 수 있으며 사용자의 데이터 소비자는 컬렉션의 내용을 수정할 수 없습니다 .

이 방법은 보기의 인터페이스의 관점에서 읽기 전용하지만 같은 방법은 실패하고 예외를 throw하는 컬렉션 추가 호출 시도가 아니다.

다른 멤버를 보호하려면 클래스 내의 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를 읽기 전용으로 설정합니다. 즉, 부모 용 설정자가 아니며 ChildNodes에 대해 IEnumerable 을 반환합니다. (2) 카테고리 트리의 경우 카테고리를 사용자가 만든 것처럼 ITreeNode를 구현합니다. (3) Tree Control의 경우 "new"키워드를 사용하여 ChildNodes 속성을 숨기고 ChildNodes가 읽기 전용이 아닌 콜렉션을 반환하도록합니다. 맞습니까? –

+0

@Dylan Lin - 가능합니다. 그러나 트리 컨트롤에서 구현을 기반으로 컬렉션에 대한 액세스를 제어 할 수 있도록 ChildNodes가 IEnumerable 을 반환하도록해야합니다. –

+0

알았어요. 많은 감사합니다. –

관련 문제