gpt4 book ai didi

c# - 在当前使用访问者模式的 C# (2.0) 中使用委托(delegate)来简化类型安全的抽象语法树

转载 作者:太空宇宙 更新时间:2023-11-03 14:33:52 25 4
gpt4 key购买 nike

我有一些“输入”可以通过多种不同的方式进行解析。

我试图从需要解析结果的各种下游引擎中抽象出解析代码(一些部分将显示它,其他部分实际执行它,等等)。

到目前为止,我有这个:

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 本身(正如您最初看到的那样)证明有点乏味。我提供了一大堆只包含一个方法的接口(interface)实现......这让我想到也许我可以使用委托(delegate)来减少膨胀:

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);
}
}

但是上面的不编译。我没有办法根据某种通用委托(delegate)来实现 IParsedNode 吗?如果有一种方法可以使它工作,那就太好了,因为事情会不那么冗长。

也许如果 IParsedNode 接口(interface)本身只是一个委托(delegate),它就可以工作吗?

最佳答案

我推荐阅读 Judith Bishop(C# 3.0 Design Patterns 的作者)题为 On the Efficiency of Design Patterns Implemented in C# 3.0 的论文.

她专门介绍了使用委托(delegate)的访问者模式,并介绍了基本实现(至少在算法上)。她的实现速度非常快,而且非常灵活。

迄今为止,这是我最喜欢的 C# 访问者模式实现。

关于c# - 在当前使用访问者模式的 C# (2.0) 中使用委托(delegate)来简化类型安全的抽象语法树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1840944/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com