Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 语法重写_C#_Parsing_Abstract Syntax Tree_Roslyn - Fatal编程技术网

C# 语法重写

C# 语法重写,c#,parsing,abstract-syntax-tree,roslyn,C#,Parsing,Abstract Syntax Tree,Roslyn,我需要使用Roslyn转换某个类的所有属性 在不使语法树中的引用无效的情况下,向语法树应用多个转换的推荐方法是什么? 以下是我的尝试和我的困境: 在第一个过程中,CSharpSyntaxWalker的后代正在访问所有PropertyDeclarationSyntax节点,并将它们存储在列表中 在第二个过程中,一个CSharpSyntaxRewriter正在转换节点,同时在转换之前检查每个访问的节点是否等于列表中的一个 我尝试的问题是:当我转换属性时,我向类添加了新字段,这会导致类发生变化。

我需要使用Roslyn转换某个类的所有属性

在不使语法树中的引用无效的情况下,向语法树应用多个转换的推荐方法是什么?


以下是我的尝试和我的困境:

  • 在第一个过程中,
    CSharpSyntaxWalker
    的后代正在访问所有
    PropertyDeclarationSyntax
    节点,并将它们存储在列表中

  • 在第二个过程中,一个
    CSharpSyntaxRewriter
    正在转换节点,同时在转换之前检查每个访问的节点是否等于列表中的一个

我尝试的问题是:当我转换属性时,我向类添加了新字段,这会导致类发生变化。列表中对其他属性的所有引用在类的新树中都将无效


重新访问整个类似乎效率低下,而且由于引用差异,我无法检测到已处理的属性节点。

我不建议从要修改的
SyntaxTree
引用节点。在您的情况下,只需在单个过程中使用
CSharpSyntaxRewriter
(不保留预处理过程中的引用)就足够了,因为它的
VisitPropertyDeclaration
方法只会对每个属性调用一次,因此不需要跟踪您已经修改的节点

CSharpSyntaxRewriter
还自下而上访问节点,因此应该始终使用原始树中的节点调用重写。很可能是在将其引用与存储的引用进行比较之前,通过调用
base.VisitPropertyDeclaration()
修改了
节点。所以,如果你真的愿意,你仍然可以保留和比较参考资料

public class PropertyRewriter : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        // 'node' should be still from the original syntax tree here

        node = (PropertyDeclarationSyntax)base.VisitPropertyDeclaration(node);

        // 'node' might be replaced here

        return node;
    }
}
您可以对它们进行注释,而不是保留对要修改的节点的引用。只要不替换节点本身,对节点的注释将在包含
SyntraxTree
的修改后仍然有效。您可以这样添加它们:

node = node.WithAdditionalAnnotations(
        new SyntaxAnnotation("propertyToChange", "todo"));

要再次检索批注,请使用
node.GetAnnotations(“propertyToChange”)
或使用
GetAnnotatedNodeOrTokens(“propertyToChange”)
检索具有给定类型批注(“propertyToChange”)的所有节点或令牌.

我不建议从要修改的
语法树中引用节点。在您的情况下,只需在单个过程中使用
CSharpSyntaxRewriter
(不保留预处理过程中的引用)就足够了,因为它的
VisitPropertyDeclaration
方法只会对每个属性调用一次,因此不需要跟踪您已经修改的节点

CSharpSyntaxRewriter
还自下而上访问节点,因此应该始终使用原始树中的节点调用重写。很可能是在将其引用与存储的引用进行比较之前,通过调用
base.VisitPropertyDeclaration()
修改了
节点。所以,如果你真的愿意,你仍然可以保留和比较参考资料

public class PropertyRewriter : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        // 'node' should be still from the original syntax tree here

        node = (PropertyDeclarationSyntax)base.VisitPropertyDeclaration(node);

        // 'node' might be replaced here

        return node;
    }
}
您可以对它们进行注释,而不是保留对要修改的节点的引用。只要不替换节点本身,对节点的注释将在包含
SyntraxTree
的修改后仍然有效。您可以这样添加它们:

node = node.WithAdditionalAnnotations(
        new SyntaxAnnotation("propertyToChange", "todo"));

若要再次检索批注,请使用
node.GetAnnotations(“propertyToChange”)
或使用
GetAnnotatedNodeOrTokens(“propertyToChange”)
检索具有给定类型批注(“propertyToChange”)的所有节点或令牌。

您能否更详细地描述您正在执行的操作?可能会显示一些代码?我已经在原始帖子中添加了更多信息,我认为您只需发布相关代码;我不完全清楚你在做什么。@DanPuzey我已经编辑了这个问题,请让我知道OP的问题在你看来是否更清楚。你能更详细地描述一下你在做什么吗?可能会显示一些代码?我已经在原始帖子中添加了更多信息,我认为您只需发布相关代码;我不完全清楚你在做什么。@DanPuzey我已经编辑了这个问题,请让我知道OP的问题在你看来是否更清楚。