2017-03-02 5 views

Antwort

1

Rufen Sie in Ihrem Projekt GetCompilationAsync() auf, um die Kompilierung zu erhalten. Von dort aus können Sie die GlobalNamespace-Eigenschaft betrachten, die Ihnen den globalen Namespace zur Verfügung stellt, und dort können Sie zu untergeordneten Namespaces und Typen aus Ihrem Code und allen zusammengeführten Referenzen gehen. Wenn Sie Typen in bestimmten Verweisen ausführen möchten, können Sie GetAssemblyOrModuleSymbol aufrufen, um eine bestimmte Metadatenreferenz anzugeben, und Sie können dann auch von dort aus weitergehen.

0
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(); 
    } 
    // .... 
} 
+0

Während es funktioniert, gibt es es sowieso nur mit Roslyn tun? Ich erkunde den SymbolApi, aber noch keinen Erfolg. –

+0

Es gibt eine Reihe von Problemen: Die Anzeige ist nicht garantiert ein Pfad, und ReflectionOnlyLoads funktioniert möglicherweise nicht in vielen portablen/Cross-Targeting-Situationen. Siehe meine andere Antwort. –

+0

@JasonMalinowski Danke für die Erklärung. –

1

fand ich einen Weg, um die Klassen und Methoden durch Micrososoft.CodeAnalysis Symbol Api zu erhalten, inspiriert sehr von Kevin Pilch-Bisson Post in Msdn Blog.

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); 
     } 
    } 
} 

Auf diese Weise muss ich System.Reflection nicht verwenden. Hoffe, es hilft jemandem irgendwann.

+0

Es sieht interessant aus und könnte nützlich sein. :) –

Verwandte Themen