首页 > 解决方案 > 从调用中获取函数的精确定义,该调用在接口中定义,但使用 Roslyn 在 C# 中的多个位置实现

问题描述

我看到有很多关于这个主题的问题(C#、Roslyn、Find References and Definitions)。但我仍然没有得到我想要的答案。这里是解释。我有界面:

public interface IRepository {      
    IEnumerable<X> Abc(long customerIdentity, ...);        
}                        

现在,这个接口由 on 类实现,例如:

public abstract class RepositoryBase : IRepository {
 public virtual IEnumerable<X> Abc(long customerIdentity, long? associatedOrderIdentity, ...) { ... }      
}

由于这是抽象类,那么其他类可能已经重新定义了这个方法,因为这个方法是虚拟的。此外,接口也可以与其他接口具有属性。

public sealed class CustRepository : RepositoryBase {
   public override IEnumerable<X> Abc(long customerIdentity, long? associatedOrderIdentity, ...){ ... }       
}

另一件事是这样的

public interface IRepositoryManager { 
    IRepository Repository { get; }
}

在我的类变量中声明如下: private IRepositoryManager _repositoryManager;我可以这样调用方法: this._repositoryManager.Repository.Abc(customerIdentity, ...)

这是我现在的问题。

  1. 我如何知道它将在运行时调用哪个方法?我希望它使用 Roslyn 获得定义/声明。我可以使用调用表达式来获取此语句。
  2. 我应该从直接实现接口的基类中获取方法吗?还是我需要查看继承链中的定义?

我从这里 和这里 找到了一些有用的答案 :这里

请不要关闭这个问题,因为我真的很难得到这个答案。提前致谢!!.

标签: c#symbolsroslynanalysis

解决方案


目前我有这段代码可以使用 Roslyn API 获取一些信息。

var syntaxTree = await document.GetSyntaxTreeAsync().ConfigureAwait(false);
                    var sm = await document.GetSyntaxTreeAsync().ConfigureAwait(false);
                    var semantic = compilation.GetSemanticModel(sm);
                    var invocations = (from d in syntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>() select d).ToList();
                    foreach (var invocation in invocations)
                    {
                        // if (!invocation.Expression.ToString().Contains("FindAlertsByLimit") && !invocation.Expression.ToString().Contains("FindAlertsByWindow")) continue;
                        var ms = semantic.GetSymbolInfo(invocation).Symbol;
                        if (ms == null) continue;
                        var referencesTo = await SymbolFinder.FindReferencesAsync(ms, document.Project.Solution).ConfigureAwait(false);
                        Console.WriteLine(referencesTo);
                        var de = SymbolFinder.FindDeclarationsAsync(project, referencesTo.First().Definition.Name, false, SymbolFilter.Member).ConfigureAwait(false).GetAwaiter().GetResult().ToList();
                        Console.WriteLine(de);
                        // other approach
                        IMethodSymbol methodSymbol = semantic.GetSymbolInfo(invocation).Symbol as IMethodSymbol;
                        if (methodSymbol == null) continue;
                        var syntaxReferences = methodSymbol.DeclaringSyntaxReferences.ToList();
                        if (!syntaxReferences.Any()) continue;
                        var declaration = syntaxReferences.First().GetSyntax();
                        var semanticModel = compilation.GetSemanticModel(declaration.SyntaxTree);
                        Console.WriteLine(semanticModel.SyntaxTree.FilePath);
}

但似乎我没有得到确切的方法定义。


推荐阅读