2014-05-21 3 views
2

나는 리스프 스타일 plist에 대한 추상 구문을 만들려고합니다. 예를 들어 :개체 지향 중첩 된 사전 데이터 구조

Plist -> { Key Value }* 
Key -> string 
Value -> string | Plist 

나는 C#에서이 데이터 구조를 표현해야

(:A 1 :B (:X 3 :Y 2) :C 4) 

여기에 지금까지 (EBNF에서) 문법이다. 불행히도, 나는 비 터미널 용 클래스를 만들기 위해 고심 중이다. 이것은 파이썬 (문자열이나 dicts 값을 가진 dict)과 같이 동적으로 형식화 된 언어에서는 사소한 것처럼 보입니다. 그러나 C#에서는 값이 plist인지 또는 다형성의 문자열인지 데이터 구조의 사용자가 어떻게 알 수 있습니까?

interface Value { } 

class PList : Value 
{ 
    private Dictionary<string, Value> Dict; 

    public Value this[string key] 
    { 
     get 
     { 
      return Dict[key]; 
     } 
    } 
} 

class String : Value 
{ 
    public string Datum { get; set; } 
} 
+0

값 대신 object를 사용하면 새 객체 [] {#} 또는 새 사전을 객체로 추가 할 수 있습니다. 그러면 재귀 적 메소드를 사용하여 액세스하고 처리 할 수 ​​있습니다. – Bit

답변

3

당신이 올바른 궤도에 확실히 위치 :

는 여기에 지금까지 가지고있는 C# 코드입니다. 사용하려는 패턴은 Composite Pattern입니다. 이 패턴에서는 공통 동작 또는 공통 추상화가 리프 및 내부 노드에 사용됩니다 (예 : 트리 및 예제에서 모두). 그런 다음 추상화는과 같이 합성에 사용되는이 디자인

public interface IValue 
{ 
    public void OperationOnValue(); 
    public List<IValue> GetChildren(); 
} 

public class CompositePList : IValue 
{ 
    private Dictionary<string, IValue> dict; 

    public void OperationOnValue() 
    { 
     foreach(var things in dict) 
     {}//things to do 
    } 

    public List<IValue> GetChildren() 
    { 
     return dict.Select(keyValue => keyValue.Value).ToList(); 
    } 
} 

public class StringValue : IValue 
{ 
    private string leafValue; 
    public void OperationOnValue() 
    {}//thing to do 

    public List<Children> GetChildren() 
    { 
     return null; //or return new List<Children>() 
    } 
} 

당신이 루트 IValue이 다음 다형 거기에 OperationOnValue()를 호출 할 수 있습니다. 당신이 염두에두고있는 기능이 더 있습니까?

+0

복합 패턴이 확실히 도움이됩니다. 공통적 인 추상화는 기본 값에 대한 문자열을 반환해야하지만 중첩 된 값에 대해서는 plist를 반환해야합니다 (lisp의 [getf] (http://clhs.lisp.se/Body/f_getf.htm)와 유사). 이 패턴과 문제가 발생할 것으로 보인다. 연산이 이러한 여러 유형을 어떻게 반환 할 수 있습니까? – ElliotPenson

+0

패턴의 요점은 다른 것들을 돌려 보내지 않아도된다는 것입니다. 'IValue' 만 있습니다. 다시 말해, 데이터 구조는 근본적으로 루트 인'IValue'가 될 것이고, 그러면 Operation을하기 위해'OperationOnValue()'를 호출 할 것입니다. 만약 다른 메소드가 자식'IValue'를 리턴한다면 당신은'IValue'의 타입을 검사 할 필요없이 데이터 구조를 거칠 수 있습니다. 이 시나리오에서도 리프 노드 (당신이하는)에 특별한 것을하고 싶다면 여전히'IValue가 StringValue'인지 확인해야합니다. –

+0

@ElliotPenson GetChildren()에 대한 편집을 보았습니다. –