当试图在给定的编译中获取类型的集合时,我对解决问题的方法感到困惑。本质上,似乎返回结果的方法不会,反之亦然。下面是调试会话即时窗口的输出,其中appCompilation
类型为Compilation
(natch)。
**appCompilation.GlobalNamespace.GetMembers()**
Count = 14
[0]: "Namespace Registration"
[1]: "Namespace Payments"
[2]: "Namespace Foo"
[3]: "NamedType <Module>"
[4]: "NamedType <Module>"
[5]: "NamedType <Module>"
[6]: "NamedType <Module>"
[7]: "NamedType <Module>"
[8]: "NamedType <Module>"
[9]: "NamedType <Module>"
[10]: "Namespace Conference"
[11]: "Namespace System"
[12]: "NamedType <>f__AnonymousType0<<OrderId>j__TPar>"
[13]: "Namespace Infrastructure"
**appCompilation.GlobalNamespace.GetTypeMembers()**
{System.Linq.Enumerable.OfTypeIterator<Roslyn.Compilers.CSharp.NamedTypeSymbol>}
source: null
**appCompilation.GlobalNamespace.GetNamespaceMembers()**
{System.Linq.Enumerable.OfTypeIterator<Roslyn.Compilers.CSharp.NamespaceSymbol>}
source: null
所以我的问题是:当我调用==.GetTypeMembers()
的符号时,我得到空值。当我调用相同的符号时,我也会得到空值。然而,当我打电话时,我得到了大量的命名空间和类型!Kind
Namespace
.GetNamespaceMembers()
.GetMembers()
更奇怪的是,我可以将此语句放入监视窗口并获得非空、非空结果!
appCompilation.GlobalNamespace.GetNamespaceMembers(), results
可能相关:启动查询的执行似乎并没有在我预期的时候发生,但我不完全确定我应该如何甚至为什么我应该担心这个......调用.ToList()
有时会触发执行。我原以为,虽然很多方法都提供了CancellationToken
参数,但它们都是同步运行的。还有一个问题是各种GetXXX()
方法都返回ReadOnlyArray
or IEnumerable
; 只读似乎不像 IEnumerable 那样从 LINQ 扩展方法中获得相同的行为。
从调试输出的表面扫描来看,它看起来像GetTypeMembers
一个GetMembers()
调用.OfType<>
。也许是因为翻译变得无聊了?
无论如何,访问和执行查询的不一致是非常痛苦的,所以我希望有人能帮助我理解我所缺少的东西,这使得事情看起来如此不确定。
编辑:在对它进行了一点迭代之后,我发现你只需要通过符号树进行递归搜索,而且查询语法有时比 lambda 表达式更容易......哦,是的 - PEBKAC,因为它似乎即时窗口阻碍的不仅仅是帮助调试工作。
从给定编译中检索所有类型的最终传递查询示例,最多三个命名空间嵌套级别左右(需要更多测试来涵盖这些情况):
由此(这比其他一些尝试要好得多!)
appCompilation.Assembly.GlobalNamespace.GetNamespaceMembers()
.SelectMany(x => x.GetNamespaceMembers().Select(y => y.GetNamespaceMembers()))
.SelectMany(x => x, (symbols, symbol) => symbol.GetTypeMembers())
.SelectMany(x => x);
为此(仍然没有完全递归,但现在已经足够好了):
from glob in appCompilation.Assembly.GlobalNamespace
.GetMembers()
.OfType<NamespaceOrTypeSymbol>()
from childNs in glob
.GetMembers()
.OfType<NamespaceSymbol>()
from childTypes in childNs
.GetTypeMembers()
select childTypes;