2017-03-02 42 views

回答

1

在你的項目上,調用GetCompilationAsync()來獲得編譯。從那裏你可以看到GlobalNamespace屬性,它給你全局命名空間,在那裏你可以從代碼中走到子命名空間和類型,並且所有引用合併在一起。如果你想在特定的引用中遍歷類型,你可以調用GetAssemblyOrModuleSymbol給它一個特定的元數據引用,然後它可以讓你從那裏走。

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

雖然它的確行得通,但有沒有辦法只使用roslyn?我正在探索SymbolApi,但尚未成功。 –

+0

這有很多問題:顯示不能保證是一個路徑,而ReflectionOnlyLoads可能無法在很多便攜/跨目標的情況下工作。看到我的其他答案。 –

+0

@JasonMalinowski感謝您的解釋。 –

1

我發現通過獲取符號Micrososoft.CodeAnalysis API的類和方法,通過Kevin Pilch-Bisson後在MSDN博客非常鼓舞的一種方式。

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。希望在某個時候幫助別人。

+0

這看起來很有趣,可能會有用。 :) –