나는 여러 가지 다른 방법으로 구문 분석되는 "입력"을 가지고 있습니다.대리자를 사용하여 현재 방문자 패턴을 사용하는 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 인터페이스 자체가 단지 대리인 일 경우이 작업이 가능할 수 있습니까?
확실히 "대리인 T 노드 유형"에 "공개"키워드가 누락 되었습니까? –