是否可以从 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 给它一个特定的元数据引用,然后你也可以从那里遍历。