You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Roslyn的CSharpSyntaxRewriter:同步修改接口与实现类方法签名

Sync Interface Method Signature Changes in Your CSharpSyntaxRewriter

Got it, let's break down how to solve this problem. You've already got a CustomRewriter that modifies method signatures in classes, but now you need to sync those changes to the corresponding interface definitions when the method implements an interface method. Here's a step-by-step approach:

1. Pass the SemanticModel to Your Rewriter

Syntax alone isn't enough to reliably link class methods to their interface counterparts—you need semantic analysis. First, update your CustomRewriter to accept a SemanticModel in its constructor, since we'll need it to resolve symbols:

public class CustomRewriter : CSharpSyntaxRewriter
{
    private readonly SemanticModel _semanticModel;
    private List<INamedTypeSymbol> _implementedInterfaces;

    public CustomRewriter(SemanticModel semanticModel)
    {
        _semanticModel = semanticModel;
        _implementedInterfaces = new List<INamedTypeSymbol>();
    }
}

2. Collect Implemented Interfaces in VisitClassDeclaration

When visiting a class, grab all the interfaces it implements and store their symbols. This lets us check later if a method belongs to any of these interfaces:

public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
    // Get the semantic symbol for the class
    if (_semanticModel.GetSymbolInfo(node).Symbol is INamedTypeSymbol classSymbol)
    {
        // Collect all implemented interfaces (including inherited ones)
        _implementedInterfaces = classSymbol.AllInterfaces.ToList();
    }

    // Proceed with the default class visit, then apply any changes
    var rewrittenClass = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
    return rewrittenClass;
}

3. Check if a Method Implements an Interface Method

In VisitMethodDeclaration, use the semantic model to determine if the current method is an implementation of an interface method. This handles both implicit and explicit implementations:

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
    var rewrittenMethod = node;

    // First, apply your existing logic to add parameters (your working code)
    if (IsDataCallMethod(node)) // Replace with your existing check for data call methods
    {
        rewrittenMethod = AddParameterToMethod(rewrittenMethod); // Your existing method modification logic

        // Now check if this method implements an interface method
        if (_semanticModel.GetSymbolInfo(node).Symbol is IMethodSymbol methodSymbol)
        {
            // Handle implicit implementations: find the matching interface method
            var interfaceMethod = FindCorrespondingInterfaceMethod(methodSymbol);

            // Handle explicit implementations (e.g., IMyInterface.MyMethod())
            if (interfaceMethod == null && methodSymbol.ExplicitInterfaceImplementations.Any())
            {
                interfaceMethod = methodSymbol.ExplicitInterfaceImplementations.First();
            }

            if (interfaceMethod != null)
            {
                // Sync the interface's method signature to match the rewritten class method
                SyncInterfaceMethodSignature(interfaceMethod, rewrittenMethod);
            }
        }
    }

    return rewrittenMethod;
}

// Helper to find the interface method a class method implements
private IMethodSymbol FindCorrespondingInterfaceMethod(IMethodSymbol classMethod)
{
    foreach (var interfaceSymbol in _implementedInterfaces)
    {
        var interfaceMethod = interfaceSymbol.GetMembers(classMethod.Name)
            .OfType<IMethodSymbol>()
            .FirstOrDefault(m => m.MatchesSignature(classMethod));
        if (interfaceMethod != null)
        {
            return interfaceMethod;
        }
    }
    return null;
}

// Helper to check if two methods have matching signatures
private static bool MatchesSignature(this IMethodSymbol method1, IMethodSymbol method2)
{
    if (method1.Name != method2.Name || method1.ReturnType != method2.ReturnType)
        return false;
    if (method1.Parameters.Count != method2.Parameters.Count)
        return false;

    for (int i = 0; i < method1.Parameters.Count; i++)
    {
        if (method1.Parameters[i].Type != method2.Parameters[i].Type)
            return false;
    }

    return true;
}

4. Sync the Interface Method Signature

Once you've identified the corresponding interface method, find its syntax node, modify its signature to match the rewritten class method, and replace it in the syntax tree:

private void SyncInterfaceMethodSignature(IMethodSymbol interfaceMethod, MethodDeclarationSyntax rewrittenClassMethod)
{
    // Get the interface method's syntax node from its semantic location
    var interfaceMethodSyntax = _semanticModel.SyntaxTree.GetRoot()
        .FindNode(interfaceMethod.Locations.First().SourceSpan) as MethodDeclarationSyntax;

    if (interfaceMethodSyntax != null)
    {
        // Create a new interface method with the updated parameters (and return type if needed)
        var updatedInterfaceMethod = interfaceMethodSyntax
            .WithParameterList(rewrittenClassMethod.ParameterList)
            .WithReturnType(rewrittenClassMethod.ReturnType); // Uncomment if you modify return types too

        // Replace the old interface method with the updated one in the root tree
        var newRoot = _semanticModel.SyntaxTree.GetRoot().ReplaceNode(interfaceMethodSyntax, updatedInterfaceMethod);
        // Note: If rewriting an entire solution, track the updated root or integrate this into your overall tree handling
    }
}

Key Notes

  • Explicit Implementations: The ExplicitInterfaceImplementations property handles cases where methods are written as IMyInterface.MyMethod().
  • Semantic Reliability: Using SemanticModel ensures you're linking the correct method symbols, even with overloaded methods or similarly named interfaces.
  • Immutability: Remember syntax nodes are immutable—always create new nodes and replace them in the tree instead of modifying existing ones.

内容的提问来源于stack exchange,提问作者jrandomuser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:56:58