在尝试获取给定编译中的类型集合时,我对于解决问题的方法感到困惑。基本上,似乎返回结果的方法不会,反之亦然。下面是调试会话立即窗口的输出,其中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()
时,我也会得到null。
然而,当我打电话给.GetMembers()
时,我得到名称空间和类型丰富!
Weirder仍然,我可以将此语句放入监视窗口并获得非空的非空结果!
appCompilation.GlobalNamespace.GetNamespaceMembers(), results
可能相关:
在我预期的时候似乎没有发起查询的执行,但我不确定如何甚至为什么我应该担心这一点......调用.ToList()
有时会触发执行。我曾经想过,即使许多方法提供CancellationToken
参数,它们都会同步运行。一个问题是各种GetXXX()
方法返回ReadOnlyArray
或IEnumerable
;只读也没有像IEnumerable那样从LINQ扩展方法中获取相同的行为。
从调试输出的表面扫描判断,它看起来像GetTypeMembers
及其“GetMembers()
.OfType<>
调用appCompilation.Assembly.GlobalNamespace.GetNamespaceMembers()
.SelectMany(x => x.GetNamespaceMembers().Select(y => y.GetNamespaceMembers()))
.SelectMany(x => x, (symbols, symbol) => symbol.GetTypeMembers())
.SelectMany(x => x);
。也许是因为翻译事情变得越来越糟糕了?
无论如何,访问和执行查询的不一致都非常痛苦,所以我希望有人可以帮助我理解我所缺少的东西,这使得事情看起来非常不确定。
编辑:在稍微迭代之后,我发现你只需要通过符号树进行递归搜索,而且查询语法可能比lambda表达式更容易...而且是的 - 是的 - PEBKAC因为看起来立即窗口不仅仅是帮助调试工作。Final Passing查询示例,它从给定的编译中检索所有类型,最多达到三个命名空间嵌套的级别(需要更多测试来覆盖这些情况):
从此(这比其他一些尝试要好得多!)
from glob in appCompilation.Assembly.GlobalNamespace
.GetMembers()
.OfType<NamespaceOrTypeSymbol>()
from childNs in glob
.GetMembers()
.OfType<NamespaceSymbol>()
from childTypes in childNs
.GetTypeMembers()
select childTypes;
对此(仍然不完全递归,但现在已经足够好了):
{{1}}
答案 0 :(得分:2)
我认为这只是立即窗口的限制,与Roslyn无关。
例如,使用以下代码:
var ints = new object[] { 2 }.OfType<int>();
我在立即窗口中得到此输出:
ints
{System.Linq.Enumerable.OfTypeIterator<int>}
source: null
System.Collections.Generic.IEnumerator<TResult>.Current: 0
System.Collections.IEnumerator.Current: 0
但是如果我使用foreach
迭代集合,或者在观察窗口中使用结果视图,它可以正常工作。
您看到自己所做的是因为Enumerable.OfType()
是使用迭代器块编写的,它生成迭代器类型。迭代器类型有一些字段具有不可描述的名称,包括<>3__source
保存原始源(我的示例中的数组)。它还有一个具有正常名称的字段:source
,在GetEnumerator()
的调用中设置。由于您尚未调用该方法,source
为null
。