Frage

Beim Versuch, eine Sammlung von Typen in einer bestimmten Zusammenstellung zu erhalten, bin ich völlig verwirrt darüber, wie ich das Problem angehen soll.Im Wesentlichen tun Methoden, die anscheinend Ergebnisse liefern, dies nicht und umgekehrt.Unten sehen Sie die Ausgabe aus einem Debug-Sitzungs-Direktfenster, in dem appCompilation ist vom Typ 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

Also meine Frage ist das:Wenn ich anrufe .GetTypeMembers() auf einem Symbol von Kind == Namespace, bekomme ich null.Wenn ich anrufe .GetNamespaceMembers() für das gleiche Symbol bekomme ich auch null.Doch wenn ich anrufe .GetMembers() Ich bekomme jede Menge Namespaces und Typen!

Seltsamer noch, ich kann diese Anweisung in ein Überwachungsfenster einfügen und nicht leere Ergebnisse ungleich Null erhalten!

appCompilation.GlobalNamespace.GetNamespaceMembers(), results

Möglicherweise relevant:Das Einleiten der Ausführung einer Abfrage scheint nicht zu geschehen, wenn ich es erwarte, aber ich bin mir nicht ganz sicher, wie oder warum ich mir darüber Sorgen machen sollte...Aufruf .ToList() manchmal wird die Ausführung ausgelöst.Ich hatte gedacht, dass, obwohl viele Methoden eine bieten CancellationToken parameter laufen sie alle synchron.Ein Problem ist auch, dass die verschiedenen GetXXX() methoden geben entweder zurück ReadOnlyArray oder IEnumerable;die schreibgeschützte Funktion scheint nicht dasselbe Verhalten von den LINQ-Erweiterungsmethoden auf die gleiche Weise wie IEnumerable zu übernehmen.

Nach einem Oberflächenscan der Debugging-Ausgabe zu urteilen, sieht es so aus GetTypeMembers und seinesgleichen Wrap GetMembers() mit einem .OfType<> nennen.Vielleicht ist es in dieser Übersetzung, dass die Dinge langweilig werden?

Auf jeden Fall war die Inkonsistenz beim Zugriff auf und Ausführen von Abfragen ziemlich schmerzhaft, daher hoffe ich, dass mir jemand helfen kann zu verstehen, was mir fehlt, was die Dinge so nicht deterministisch erscheinen lässt.

BEARBEITEN:Nachdem ich ein wenig dagegen iteriert hatte, stellte ich fest, dass Sie nur eine rekursive Suche durch den Symbolbaum durchführen müssen und dass die Abfragesyntax manchmal ein viel einfacherer Ansatz sein kann als Lambda-Ausdrücke...und oh ja - PEBKAC, da es den Anschein hat, dass das unmittelbare Fenster mehr behindert hat, als die Debugging-Bemühungen zu unterstützen.

Endgültiges Abfragebeispiel für die Übergabe, das alle Typen aus einer bestimmten Kompilierung abruft, bis zu einer Ebene von etwa drei Namespace-Verschachtelungen (weitere Tests sind erforderlich, um diese Fälle abzudecken):

Daraus (und das ist weitaus besser als einige andere Versuche!)

appCompilation.Assembly.GlobalNamespace.GetNamespaceMembers()
    .SelectMany(x => x.GetNamespaceMembers().Select(y => y.GetNamespaceMembers()))
    .SelectMany(x => x, (symbols, symbol) => symbol.GetTypeMembers())
    .SelectMany(x => x);

Dazu (immer noch nicht vollständig rekursiv, aber vorerst gut genug):

from glob in appCompilation.Assembly.GlobalNamespace
    .GetMembers()
    .OfType<NamespaceOrTypeSymbol>()
from childNs in glob
    .GetMembers()
    .OfType<NamespaceSymbol>()
from childTypes in childNs
    .GetTypeMembers()
select childTypes;
War es hilfreich?

Lösung

Ich denke, dies ist nur eine Einschränkung beim unmittelbaren Fenster, die nichts mit Roslyn zu tun hat.

Zum Beispiel mit dem folgenden Code:

var ints = new object[] { 2 }.OfType<int>();

Ich bekomme diese Ausgabe im Direktfenster:

ints
{System.Linq.Enumerable.OfTypeIterator<int>}
    source: null
    System.Collections.Generic.IEnumerator<TResult>.Current: 0
    System.Collections.IEnumerator.Current: 0

Aber wenn ich die Sammlung mit einem iteriere foreach, oder verwenden Sie die Ergebnisansicht in einem Überwachungsfenster, es funktioniert ordnungsgemäß.

Der Grund, warum Sie sehen, was Sie tun, ist, weil Enumerable.OfType() wird mit einem Iteratorblock geschrieben, der den Iteratortyp generiert.Der Iteratortyp enthält einige Felder mit unaussprechlichen Namen, darunter <>3__source welches die ursprüngliche Quelle enthält (das Array in meinem Beispiel).Es hat auch ein Feld mit einem normalen Namen: source, die im Aufruf an gesetzt wird GetEnumerator().Da du diese Methode noch nicht aufgerufen hast, source is null.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top