我可以使用以下代码从对特定方法的所有调用的解决方案中获取列表:
var createCommandList = new List<MethodSymbol>();
INamedTypeSymbol interfaceSymbol =
(from p
in solution.Projects
select p.GetCompilation().GetTypeByMetadataName(
"BuySeasons.BsiServices.DataResource.IBsiDataConnection")
).FirstOrDefault();
foreach (ISymbol symbol in interfaceSymbol.GetMembers("CreateCommand"))
{
if (symbol.Kind == CommonSymbolKind.Method
&& symbol is MethodSymbol)
{
createCommandList.Add(symbol as MethodSymbol);
}
}
foreach (MethodSymbol methodSymbol in createCommandList)
{
foreach (ReferencedSymbol referenceSymbol
in methodSymbol.FindReferences(solution))
{
foreach (ReferenceLocation referenceLocation
in from l
in referenceSymbol.Locations
orderby l.Document.FilePath
select l)
{
if (referenceLocation.Location.GetLineSpan(false)
.StartLinePosition.Line ==
referenceLocation.Location.GetLineSpan(false)
.EndLinePosition.Line)
{
Debug.WriteLine("{0} {1} at {2} {3}/{4} - {5}",
methodSymbol.Name,
"(" + String.Join(",",
(from p
in methodSymbol.Parameters
select p.Type.Name + " " + p.Name).ToArray()
) + ")",
Path.GetFileName(referenceLocation.Location.GetLineSpan(false)
.Path),
referenceLocation.Location.GetLineSpan(false)
.StartLinePosition.Line,
referenceLocation.Location.GetLineSpan(false)
.StartLinePosition.Character,
referenceLocation.Location.GetLineSpan(false)
.EndLinePosition.Character));
}
else
{
throw new ApplicationException("Call spans multiple lines");
}
}
}
}
但这给了我一个ReferencedSymbol
列表.虽然这给了我调用该方法的文件和行号,但我也想获取调用该方法的特定参数。如何转换我所拥有的内容或通过 Roslyn 获取相同的信息?(请注意,我首先使用 Solution.Load
方法加载解决方案,然后循环查找方法的定义/声明位置 ( createCommandList
))。
您已经在这里使用了 Roslyn。当你有一个referenceSymbol
,你可以获取方法声明语法,然后向下查看树以获取参数列表。
我插入了一个使用您的referenceSymbol
的arguments
变量:
// Snip start
foreach (MethodSymbol methodSymbol in createCommandList)
{
foreach (ReferencedSymbol referenceSymbol
in methodSymbol.FindReferences(solution))
{
var arguments = referenceSymbol.Definition.DeclaringSyntaxNodes.First()
.DescendantNodes().OfType<ParameterSyntax>().ToList();
foreach (ReferenceLocation referenceLocation in
from l
in referenceSymbol.Locations
orderby l.Document.FilePath
select l)
{
// Snip end
执行调试输出时,可以使用该参数列表来获取名称。
我的解决方案需要获取DeclaringSyntaxNodes
的First()
,我不太喜欢,但找不到另一种方法来获取语法树的后代节点。
我发现了另一种从方法获取参数列表的方法的方法,该方法也可能适用于其他人。
假设我有以下方法,它有两个参数:
public string DebugPage(string enabled, string show){
//do stuff
}
然后,您可以随心所欲地获得节点。例如,这给了我一个公共方法列表:
IEnumerable<MethodDeclarationSyntax> methods = from m in root.DescendantNodes().OfType<MethodDeclarationSyntax>() where m.Modifiers.ToString().Contains("public") select m;
然后,我可以循环访问该方法列表,以获取该方法的 ParameterList 属性,该属性已公开,以使此操作变得非常简单。在此循环结束时,列表parameters
将保存方法中每个参数的名称(在上面的Debug
方法的示例中,它将按预期保存值enabled
和show
):
var parameters = new List<string>();
foreach (var method in methods)
{
foreach (var n in method.ParameterList.Parameters)
{
var parameterName = n.Identifier.Text;
parameters.Add(parameterName);
}
}
可以在引用发生的特定源位置搜索引用的语法树,以查找要查找的节点。您需要从树的根节点使用像 DescendentNode 这样的调用,并且可能需要请求要查找的特定语言节点类型。一旦你在引用树中有了节点,你就可以使用该树的语义模型来告诉你关于参数的其他信息。