是否可以从 Project MetaDataReferences 获取实现细节?
Is it possible to obtain implementation details from a Project MetaDataReferences?
从通过 MSBuildWorkspace 获得的解决方案 s 中获得项目 p,是否可以获取该项目 MetadataReferences(在本例中为 .dll)的详细信息,例如 类 和方法?
foreach (var mRef in project.MetadataReferences)
{
Type[] assemblyTypes;
if (!File.Exists(mRef.Display))
continue;
try
{
assemblyTypes = Assembly.ReflectionOnlyLoadFrom(mRef.Display)
.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
assemblyTypes = e.Types
.Where(type => type != null)
.ToArray();
}
// ....
}
我找到了通过Micrososoft.CodeAnalysis符号Api获取类的方法和方法,受到msdn博客Kevin Pilch-Bissonpost的启发。
private void GetSymbolsTest(ref Project project, ref MetadataReference metaRef)
{
if (!project.MetadataReferences.Contains(metaRef))
throw new DllNotFoundException("metadatarefence not in project");
var compilation = project.GetCompilationAsync().Result;
var metaRefName = Path.GetFileNameWithoutExtension(metaRef.Display);
SymbolCollector symCollector = new SymbolCollector();
symCollector.Find(compilation.GlobalNamespace, metaRefName);
Console.WriteLine($"Classes found: {symCollector.Classes.Count}");
Console.WriteLine($"Methods found: {symCollector.Methods.Count}");
}
public class SymbolCollector
{
public HashSet<IMethodSymbol> Methods { get; private set; } = new HashSet<IMethodSymbol>();
public HashSet<INamedTypeSymbol> Classes { get; private set; } = new HashSet<INamedTypeSymbol>();
public void Find(INamespaceSymbol namespaceSymbol, string assemblyRefName)
{
foreach (var type in namespaceSymbol.GetTypeMembers())
{
if (String.Equals(type.ContainingAssembly.Name, assemblyRefName, StringComparison.CurrentCultureIgnoreCase))
Find(type);
}
foreach (var childNs in namespaceSymbol.GetNamespaceMembers())
{
Find(childNs, assemblyRefName);
}
}
private void Find(INamedTypeSymbol type)
{
if (type.Kind == SymbolKind.NamedType)
Classes.Add(type);
foreach (var member in type.GetMembers())
{
if (member.Kind == SymbolKind.Method)
Methods.Add(member as IMethodSymbol);
}
foreach (var nested in type.GetTypeMembers())
{
Find(nested);
}
}
}
这样我就不需要用System.Reflection了。希望它能对某人有所帮助。
在您的项目中,调用 GetCompilationAsync() 获取编译。从那里您可以查看 GlobalNamespace 属性,它为您提供了全局命名空间,在那里您可以从您的代码和所有引用合并到子命名空间和类型。如果你想遍历特定引用中的类型,你可以调用 GetAssemblyOrModuleSymbol 给它一个特定的元数据引用,然后你也可以从那里遍历。
从通过 MSBuildWorkspace 获得的解决方案 s 中获得项目 p,是否可以获取该项目 MetadataReferences(在本例中为 .dll)的详细信息,例如 类 和方法?
foreach (var mRef in project.MetadataReferences)
{
Type[] assemblyTypes;
if (!File.Exists(mRef.Display))
continue;
try
{
assemblyTypes = Assembly.ReflectionOnlyLoadFrom(mRef.Display)
.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
assemblyTypes = e.Types
.Where(type => type != null)
.ToArray();
}
// ....
}
我找到了通过Micrososoft.CodeAnalysis符号Api获取类的方法和方法,受到msdn博客Kevin Pilch-Bissonpost的启发。
private void GetSymbolsTest(ref Project project, ref MetadataReference metaRef)
{
if (!project.MetadataReferences.Contains(metaRef))
throw new DllNotFoundException("metadatarefence not in project");
var compilation = project.GetCompilationAsync().Result;
var metaRefName = Path.GetFileNameWithoutExtension(metaRef.Display);
SymbolCollector symCollector = new SymbolCollector();
symCollector.Find(compilation.GlobalNamespace, metaRefName);
Console.WriteLine($"Classes found: {symCollector.Classes.Count}");
Console.WriteLine($"Methods found: {symCollector.Methods.Count}");
}
public class SymbolCollector
{
public HashSet<IMethodSymbol> Methods { get; private set; } = new HashSet<IMethodSymbol>();
public HashSet<INamedTypeSymbol> Classes { get; private set; } = new HashSet<INamedTypeSymbol>();
public void Find(INamespaceSymbol namespaceSymbol, string assemblyRefName)
{
foreach (var type in namespaceSymbol.GetTypeMembers())
{
if (String.Equals(type.ContainingAssembly.Name, assemblyRefName, StringComparison.CurrentCultureIgnoreCase))
Find(type);
}
foreach (var childNs in namespaceSymbol.GetNamespaceMembers())
{
Find(childNs, assemblyRefName);
}
}
private void Find(INamedTypeSymbol type)
{
if (type.Kind == SymbolKind.NamedType)
Classes.Add(type);
foreach (var member in type.GetMembers())
{
if (member.Kind == SymbolKind.Method)
Methods.Add(member as IMethodSymbol);
}
foreach (var nested in type.GetTypeMembers())
{
Find(nested);
}
}
}
这样我就不需要用System.Reflection了。希望它能对某人有所帮助。
在您的项目中,调用 GetCompilationAsync() 获取编译。从那里您可以查看 GlobalNamespace 属性,它为您提供了全局命名空间,在那里您可以从您的代码和所有引用合并到子命名空间和类型。如果你想遍历特定引用中的类型,你可以调用 GetAssemblyOrModuleSymbol 给它一个特定的元数据引用,然后你也可以从那里遍历。