2009-12-03 3 views
2

나는 여러 가지 다른 방법으로 구문 분석되는 "입력"을 가지고 있습니다.대리자를 사용하여 현재 방문자 패턴을 사용하는 C# (2.0)의 형식 안전 추상 구문 트리를 단순화합니다.

구문 분석 된 결과가 필요한 여러 다운 스트림 엔진에서 파싱 코드를 추상화하려고합니다 (일부 파트는이를 표시하고 다른 파트는 실제로이를 실행합니다.). 그 또한 안전 입력, 당신이 볼 수 있듯이

interface IParsedNode 
{ 
    // Visits this node, returns whatever the appropriate IVisitor function 
    // returned. 
    T Visit<T>(IVisitor<T> visitor); 
} 

interface IVisitor<T> 
{ 
    T Load(Aspect aspect); 
    T LoadFile(string group, string filename); 
    T Process(PluginProperties pluginProperties, IParsedNode input); 
    T Aggregate(List<IParsedNode> children); 
    T Rename(string newName, string oldName, IParsedNode input); 
    T Filter(string keep, IParsedNode input); 
    T Cache(IParsedNode input); 
} 

class Cached : IParsedNode 
{ 
    private readonly IParsedNode input; 

    public Cached(IParsedNode input) 
    { 
     this.input = input; 
    } 
    #region IParsedNode Members 
    public T Visit<T>(IVisitor<T> visitor) 
    { 
     return visitor.Cache(input); 
    } 
    #endregion 
} 

class Filter : IParsedNode 
{ 
    private readonly string keep; 
    private readonly IParsedNode input; 

    public Filter(string keep, IParsedNode input) 
    { 
     this.keep = keep; 
     this.input = input; 
    } 

    #region IParsedNode Members 
    public T Visit<T>(IVisitor<T> visitor) 
    { 
     return visitor.Filter(keep, input); 
    } 
    #endregion 
} 

은이 날 완전히 "추상적"파스 트리를 가질 수 있습니다 :

지금까지,이 있습니다. 나는 또한 모든 것이 불변하다는 사실을 좋아한다.

다른 다운 스트림 시스템이 추상 구문 분석 트리에서 자체의 구체적인 그래프를 생성하므로 "T"유형을 추상화합니다. 이 모두가 내가 희망을 감히보다 더 좋은 작품 IVisitor의 실제 구체적인 구현의

// Used to convert the abstract tree into an actual tree that can then be post-processed. 
class NodeTreeBuilder : IVisitor<Node> 
{ 
    private readonly NodeFactory nodeFactory; 

    public NodeTreeBuilder(NodeFactory nodeFactory) 
    { 
     this.nodeFactory = nodeFactory; 
    } 

    #region IVisitor<Node> Members 
    public Node Load(Aspect aspect) 
    { 
     return nodeFactory.CreateRaw(aspect); 
    } 

    public Node LoadFile(string group, string filename) 
    { 
     return nodeFactory.CreateFile(group, filename); 
    } 

    public Node Process(PluginProperties pluginProperties, IParsedNode input) 
    { 
     ProcessInfo processInfo = new ProcessInfo(); 
     processInfo.AssemblyPath = pluginProperties.AssemblyPath; 
     processInfo.ClassName = pluginProperties.ClassName; 
     processInfo.Config = new PluginConfig(pluginProperties.Config, pluginProperties.HashConfig, pluginProperties.DeltaType); 
     PluginInfo pluginInfo = Registry.CreatePluginInfo(pluginProperties.Id, processInfo); 
     return nodeFactory.CreatePostProcess(pluginInfo, input.Visit(this), pluginProperties.RunOnEmpty); 
    } 

    public Node Aggregate(List<IParsedNode> children) 
    { 
     Node[] convertedChildren = children.ConvertAll<Node>(delegate(IParsedNode child) { return child.Visit(this); }).ToArray(); 
     return nodeFactory.CreateAggregated(convertedChildren); 
    } 

    public Node Rename(string newName, string oldName, IParsedNode input) 
    { 
     return nodeFactory.Rename(oldName, newName, input.Visit(this)); 
    } 

    public Node Filter(string keep, IParsedNode input) 
    { 
     return nodeFactory.Filter(keep, input.Visit(this)); 
    } 

    public Node Cache(IParsedNode input) 
    { 
     return input.Visit(this).Cache(true); 
    } 
    #endregion 
} 

:

예를 들어, 여기 IVisitor의 하나의 구현입니다.

그러나 IParsedNode 자체를 구현하면 (초기에 본 것처럼) 조금 지루한 것으로 입증됩니다. 나는 내가 아마도 내가 부풀게 줄이기 위해 대리자를 사용할 수 있다고 생각하고있어 하나의 방법을 포함하는 인터페이스의 구현의 전체 무리 .... 제공하고 있습니다 :

class ParsedNode : IParsedNode 
{ 
    delegate T NodeType<T>(IVisitor<T> visitor); 

    private readonly NodeType nodeType; 

    public ParsedNode<T>(NodeType<T> nodeType) 
    { 
     this.nodeType = NodeType; 
    } 

    public T Visit<T>(IVisitor<T> visitor) 
    { 
     return nodeType(visitor); 
    } 
} 

을하지만 위하지 않습니다 엮다. 일종의 일반 대리인과 관련하여 IParsedNode를 구현할 방법이 없습니까? 상황이 덜 장황 해지면이 작업을 할 수있는 방법이 있다면 좋을 것입니다.

아마도 IParsedNode 인터페이스 자체가 단지 대리인 일 경우이 작업이 가능할 수 있습니까?

+0

확실히 "대리인 T 노드 유형 "에 "공개"키워드가 누락 되었습니까? –

답변

1

나는 주디스 비숍 (저자 : C# 3.0 Design Patterns)의 논문 On the Efficiency of Design Patterns Implemented in C# 3.0을 읽는 것이 좋습니다.

그녀는 대리인을 사용하여 Visitor 패턴을 구체적으로 처리하고 기본 구현 (적어도 알고리즘 적으로)을 수행합니다. 그녀의 구현은 매우 빠르고 유연합니다.

이것은 현재까지 C#의 Visitor 패턴을 가장 많이 사용하는 구현입니다.

관련 문제