如何获取所有具有某些属性的属性?

我刚刚开始使用Roslyn,我想找到所有使用属性名称“OneToOne”注释的属性。 我启动了SyntaxVisualizer并且能够获得对该节点的引用,但我想知道是否有更简单的方法来实现这一点。 这就是我所拥有的:

var prop = document.GetSyntaxRoot() .DescendantNodes() .OfType() .Where(p => p.DescendantNodes() .OfType() .Any(a => a.DescendantNodes() .OfType() .Any(i => i.DescendantTokens() .Any(dt => dt.Kind == SyntaxKind.IdentifierToken && dt.ValueText == "OneToOne")))) 

好吧,我会使用语义而不是语法来解决这个问题。 像(在我的头顶):

 var attributeSymbol = compilation.GetTypeByMetadataName("ConsoleApplication1.OneToOneAttribute"); var propertySymbol = compilation.GetTypeByMetadataName("ConsoleApplication1.Program") .GetMembers() .Where(m => m.Kind == CommonSymbolKind.Property && m.GetAttributes().Any(a => a.AttributeClass.MetadataName == attributeSymbol.MetadataName)); 

我对类似任务的方法(我想重写用特定属性修饰的方法和属性)是找到属性符号的所有用法,然后迭代引用并获取方法/属性声明语法:

 var attributeSymbol = compilation.FindSymbol(typeof()); var references = attributeSymbol.FindReferences(solution); foreach (ReferencedSymbol referencedSymbol in references) { foreach (ReferenceLocation location in referencedSymbol.Locations) { var propertyDeclaration = location.Document.GetSyntaxRoot() .FindToken(location.Location.SourceSpan.Start) .Parent .FirstAncestorOrSelf(); } } 

我不得不写几个扩展方法来让生活更轻松:

 public static class CompilationExtensions { public static INamedTypeSymbol FindSymbol(this CommonCompilation compilation, Type searchedType) { var splitFullName = searchedType.FullName.Split('.'); var namespaceNames = splitFullName.Take(splitFullName.Length - 1).ToArray(); var className = splitFullName.Last(); if (namespaceNames.Length == 0) return compilation.GlobalNamespace.GetAllTypes(new CancellationToken()).First(n => n.Name == className); var namespaces = compilation.GlobalNamespace.GetNamespaceMembers(); INamespaceSymbol namespaceContainingType = null; foreach (var name in namespaceNames) { namespaceContainingType = namespaces.First(n => n.Name == name); namespaces = namespaceContainingType.GetNamespaceMembers(); } return namespaceContainingType.GetAllTypes(new CancellationToken()).First(n => n.Name == className); } } public static class INamespaceSymbolExtension { public static IEnumerable GetAllTypes(this INamespaceSymbol @namespace, CancellationToken cancellationToken) { Queue symbols = new Queue(); symbols.Enqueue(@namespace); while (symbols.Count > 0) { cancellationToken.ThrowIfCancellationRequested(); INamespaceOrTypeSymbol namespaceOrTypeSymbol = symbols.Dequeue(); INamespaceSymbol namespaceSymbol = namespaceOrTypeSymbol as INamespaceSymbol; if (namespaceSymbol == null) { INamedTypeSymbol typeSymbol = (INamedTypeSymbol) namespaceOrTypeSymbol; Array.ForEach(typeSymbol.GetTypeMembers().ToArray(), symbols.Enqueue); yield return typeSymbol; } else { Array.ForEach(namespaceSymbol.GetMembers().ToArray(), symbols.Enqueue); } } } }