2015-01-18 3 views
1

ReSharper 7.1 Generator 플러그인을 작성 중이며 현재 프로젝트 (클래스, 인터페이스 및 구조체 - IDeclaredType-s)에 선언 된 모든 유형의 목록을 가져와야합니다. GeneratorProviderBase<CSharpGeneratorContext>.Populate 방법의 경우현재 프로젝트의 모든 IDeclaredType-s 가져 오기 (ReSharper Generator 플러그인 용)

정규 반영으로는 Assembly.GetTypes()처럼 간단하지만 여기서는 상당히 어려운 것으로 입증되었습니다. 이것을 할 수있는 방법이 있습니까?

그때, 워드 프로세서 샘플이 도움이되지 않았다, 높고 낮은 검색 모든 *Extensions*Util 클래스를 통해 보았지만 아무것도 유용을 찾을 수 없습니다했습니다 ...

답변

0

다음은 캐시 사용에 대한 설명입니다. 여전히 옳은 것처럼 보이지는 않지만 이전 방법보다 더 나을 것으로 기대합니다. 이것은 여전히 ​​GeneratorProvider.Populate에서 호출 :

public static IEnumerable<ICSharpTypeDeclaration> GetAllPublicTypeDeclarations(this IPsiModule module) 
{ 
    var declarationCache = module.GetPsiServices().CacheManager.GetDeclarationsCache(module, false, true); 
    var declarations = new List<ICSharpTypeDeclaration>(); 

    foreach (var shortName in declarationCache.GetAllShortNames()) 
    { 
     var declaredElements = declarationCache.GetElementsByShortName(shortName).OfType<ITypeElement>().Where(e => 
     { 
      var elementType = e.GetElementType(); 
      return elementType == CLRDeclaredElementType.CLASS || elementType == CLRDeclaredElementType.INTERFACE || elementType == CLRDeclaredElementType.ENUM; 
     }); 

     foreach (ITypeElement declaredElement in declaredElements) 
     { 
      var declaration = declaredElement.GetDeclarations().OfType<ICSharpTypeDeclaration>().FirstOrDefault(d => d.GetAccessRights() == AccessRights.PUBLIC); 
      if (declaration != null) 
      { 
       declarations.Add(declaration); 
      } 
     } 
    } 

    return declarations; 
} 

참고 : 결과는 첫 번째 대답과 동일하지 않습니다, 나는 몇 가지 제한 사항을 변경 한 원인. 또한 두 경우 모두 부분 클래스에 관심이 없습니다.

0

내가 무엇을 관리 I 필요,하지만 난 그게 올바른/가장 좋은 방법인지 정말 모르겠어요 :이 일을

[GeneratorElementProvider("MyGeneratorProvider", typeof(CSharpLanguage))] 
public class MyGeneratorProvider : GeneratorProviderBase<CSharpGeneratorContext> 
{ 
    public override double Priority 
    { 
     get { return 0; } 
    } 

    public override void Populate(CSharpGeneratorContext context) 
    { 
     var projectCsFiles = GetAllCSharpFilesInProject(context.PsiModule); 
     var declarations = projectCsFiles.SelectMany(GetDeclarationsFromCSharpFile).ToList(); 
     context.ProvidedElements.AddRange(declarations.Select(d => new GeneratorDeclarationElement(d))); 
    } 

    private static IEnumerable<ICSharpFile> GetAllCSharpFilesInProject(IPsiModule projectModule) 
    { 
     PsiManager psiManager = projectModule.GetPsiServices().PsiManager; 
     return projectModule.SourceFiles.SelectMany(f => psiManager.GetPsiFiles<CSharpLanguage>(f).OfType<ICSharpFile>()); 
    } 

    private static IEnumerable<ITypeDeclaration> GetDeclarationsFromCSharpFile(ICSharpFile file) 
    { 
     return file.NamespaceDeclarationNodes.SelectMany(GetDeclarationsFromCSharpNamespace); 
    } 

    private static IEnumerable<ITypeDeclaration> GetDeclarationsFromCSharpNamespace(ICSharpNamespaceDeclaration namespaceDeclaration) 
    { 
     foreach (var namespaceChild in namespaceDeclaration.Body.Children()) 
     { 
      var classDeclaration = namespaceChild as IClassDeclaration; 
      if (classDeclaration != null) 
      { 
       yield return classDeclaration; 
      } 
      else 
      { 
       var childNamespace = namespaceChild as ICSharpNamespaceDeclaration; 
       if (childNamespace != null) 
       { 
        foreach (var declaration in GetDeclarationsFromCSharpNamespace(childNamespace)) 
        { 
         yield return declaration; 
        } 
       } 
      } 
     } 
    } 
} 

의견이나 간단한 (어쩌면 내장) 방법?

+0

이것은 물론 제거 된 버전이며 모든 점검과 추가 조건 및 변환이 간결하게 제거되었습니다. – mbinic

+0

이것은 매우 느릴 것이며, 프로젝트가 커질수록 모든 파일을 처리하게됩니다. 더 이상 사용할 7.1이 없지만 ReSharper의 [캐시] (https://confluence.jetbrains.com/display/NETCOM/4.01+Caches+%28R7%29)에서이 정보를 얻을 수 있어야합니다. – citizenmatt

+0

감사합니다. 귀하의 의견을 위해 Matt! 캐시는 내가 처음 보았지만 짧은 이름으로는별로 도움이되지 않았다. 디버깅 세션에서 2 cs 파일 만있는 프로젝트의 경우 8000+ 개 항목을 보았다. 대부분의 이름은 수업이 아닌 참조 된 어셈블리에서 가져온 것이므로 점점 더 느려졌습니다. 어쨌든, 한번 시도해 보겠습니다. – mbinic