查找从给定 INamedTypeSymbol 继承的类型
Find types that inherit from given INamedTypeSymbol
给定一个 INamedTypeSymbol
(来自引用的程序集,而不是源代码)我如何找到继承自的所有类型(在 源代码和引用的程序集 中)这种类型?
在我的特定情况下,我正在寻找从 NUnit.Framework.TestAttribute
继承的所有类型。我可以按如下方式访问命名类型符号:
var ws = MSBuildWorkspace.Create();
var soln = ws.OpenSolutionAsync(@"C:\Users\...\SampleInheritanceStuff.sln").Result;
var proj = soln.Projects.Single();
var compilation = proj.GetCompilationAsync().Result;
string TEST_ATTRIBUTE_METADATA_NAME = "NUnit.Framework.TestAttribute";
var testAttributeType = compilation.GetTypeByMetadataName(TEST_ATTRIBUTE_METADATA_NAME);
//Now how do I find types that inherit from this type?
我看过 SymbolFinder
、Compilation
和 INamedTypeSymbol
,但我没有任何运气。
编辑: FindDerivedClassesAsync
method looks close to what I need. (I'm not 100% sure that it finds derived classes in referenced assemblies). However it's internal, so I've opened an issue.
FindDerivedClassesAsync
正是您要找的。
它在引用的程序集中找到派生的 类,如您在 DependentTypeFinder
的源代码中所见(注意 locationsInMetadata
变量)。
至于使用它,你总是可以同时进行反射:
private static readonly Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>> FindDerivedClassesAsync
= new Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>>(() => (Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>)Delegate.CreateDelegate(typeof(Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>), DependentTypeFinder.Value.GetMethod("FindDerivedClassesAsync", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)));
(code borrowed from Tunnel Vision Laboratories Github)
祝你好运!
更新:
这个方法现在已经public了。 (source)
您可以使用从 Compilation
公开的 SemanticModel 获取此信息
public static IEnumerable<INamedTypeSymbol> GetBaseClasses(SemanticModel model, BaseTypeDeclarationSyntax type)
{
var classSymbol = model.GetDeclaredSymbol(type);
var returnValue = new List<INamedTypeSymbol>();
while (classSymbol.BaseType != null)
{
returnValue.Add(classSymbol.BaseType);
if (classSymbol.Interfaces != null)
returnValue.AddRange(classSymbol.Interfaces);
classSymbol = classSymbol.BaseType;
}
return returnValue;
}
这将为您提供所有基础 class 的列表以及每个基础 class 实现的每个接口。然后您可以过滤到您感兴趣的 INamedTypeSymbol:
public static IEnumerable<BaseTypeDeclarationSyntax>
FindClassesDerivedOrImplementedByType(Compilation compilation
, INamedTypeSymbol target)
{
foreach (var tree in compilation.SyntaxTrees)
{
var semanticModel = compilation.GetSemanticModel(tree);
foreach (var type in tree.GetRoot().DescendantNodes()
.OfType<TypeDeclarationSyntax>())
{
var baseClasses = GetBaseClasses(semanticModel, type);
if (baseClasses != null)
if (baseClasses.Contains(target))
yield return type;
}
}
}
给定一个 INamedTypeSymbol
(来自引用的程序集,而不是源代码)我如何找到继承自的所有类型(在 源代码和引用的程序集 中)这种类型?
在我的特定情况下,我正在寻找从 NUnit.Framework.TestAttribute
继承的所有类型。我可以按如下方式访问命名类型符号:
var ws = MSBuildWorkspace.Create();
var soln = ws.OpenSolutionAsync(@"C:\Users\...\SampleInheritanceStuff.sln").Result;
var proj = soln.Projects.Single();
var compilation = proj.GetCompilationAsync().Result;
string TEST_ATTRIBUTE_METADATA_NAME = "NUnit.Framework.TestAttribute";
var testAttributeType = compilation.GetTypeByMetadataName(TEST_ATTRIBUTE_METADATA_NAME);
//Now how do I find types that inherit from this type?
我看过 SymbolFinder
、Compilation
和 INamedTypeSymbol
,但我没有任何运气。
编辑: FindDerivedClassesAsync
method looks close to what I need. (I'm not 100% sure that it finds derived classes in referenced assemblies). However it's internal, so I've opened an issue.
FindDerivedClassesAsync
正是您要找的。
它在引用的程序集中找到派生的 类,如您在 DependentTypeFinder
的源代码中所见(注意 locationsInMetadata
变量)。
至于使用它,你总是可以同时进行反射:
private static readonly Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>> FindDerivedClassesAsync
= new Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>>(() => (Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>)Delegate.CreateDelegate(typeof(Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>), DependentTypeFinder.Value.GetMethod("FindDerivedClassesAsync", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)));
(code borrowed from Tunnel Vision Laboratories Github)
祝你好运!
更新:
这个方法现在已经public了。 (source)
您可以使用从 Compilation
公开的 SemanticModel 获取此信息public static IEnumerable<INamedTypeSymbol> GetBaseClasses(SemanticModel model, BaseTypeDeclarationSyntax type)
{
var classSymbol = model.GetDeclaredSymbol(type);
var returnValue = new List<INamedTypeSymbol>();
while (classSymbol.BaseType != null)
{
returnValue.Add(classSymbol.BaseType);
if (classSymbol.Interfaces != null)
returnValue.AddRange(classSymbol.Interfaces);
classSymbol = classSymbol.BaseType;
}
return returnValue;
}
这将为您提供所有基础 class 的列表以及每个基础 class 实现的每个接口。然后您可以过滤到您感兴趣的 INamedTypeSymbol:
public static IEnumerable<BaseTypeDeclarationSyntax>
FindClassesDerivedOrImplementedByType(Compilation compilation
, INamedTypeSymbol target)
{
foreach (var tree in compilation.SyntaxTrees)
{
var semanticModel = compilation.GetSemanticModel(tree);
foreach (var type in tree.GetRoot().DescendantNodes()
.OfType<TypeDeclarationSyntax>())
{
var baseClasses = GetBaseClasses(semanticModel, type);
if (baseClasses != null)
if (baseClasses.Contains(target))
yield return type;
}
}
}