Frage

Wie kann ich bei einem MethodDeclarationSyntax-Objekt den deklarierenden Typ der Methode ermitteln?

Mein eigentliches Problem ist, dass ich herausfinden muss, ob die referenzierte Methode eine Schnittstellenmethode implementiert oder nicht.

Wenn ich beispielsweise im folgenden Code eine MethodDeclarationSyntax für die Dispose () -Methode habe, wie kann daraus geschlossen werden, dass es sich um die Implementierung von IDisposable.Dispose () handelt?

using System;
abstract class InterfaceImplementation : IDisposable
{
    public abstract void Dispose();
}

Ich habe erfolglos versucht, den deklarierenden Typ der Methode abzurufen (und den Typ zu überprüfen) (die Parent-Eigenschaft gibt mir die InterfaceImplementation-Klasse zurück).

Ich habe auch versucht, das semantische Symbol für die Methode zu erfassen:

var methodSymbol = (MethodSymbol) semanticModel.GetDeclaredSymbol(methodDeclaration);

konnte aber nichts erkennen, was mir helfen könnte.

Ideen?

War es hilfreich?

Lösung

Sobald Sie das Methodensymbol haben, können Sie fragen, ob eine bestimmte Methode eine Schnittstellenmethode innerhalb eines bestimmten Typs implementiert.Der Code ist ziemlich einfach:

MethodSymbol method = ...;
TypeSymbol type = method.ContainingType;
MethodSymbol disposeMethod = (MethodSymbol)c.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single();
bool isDisposeMethod = method.Equals(type.FindImplementationForInterfaceMember(disposeMethod));

Es ist wichtig zu beachten, dass davon ausgegangen wird, dass der Typ, der die Dispose-Methode enthält, der Typ ist, der angibt, dass er IDisposable implementiert.In C # kann eine Methode eine Schnittstellenmethode implementieren, die nur für einen abgeleiteten Typ angegeben ist.Genauer gesagt, wenn Sie das ": IDisposable" in Ihrem obigen Code eingegeben haben und einen abgeleiteten Typ von InterfaceImplementation hatten, der IDisposable war, kann diese Dispose () -Methode es weiterhin implementieren.

Andere Tipps

Die Syntaxtypen (wie MethodDeclarationSyntax) arbeiten nur auf syntaktischer Ebene.Auf dieser Ebene ist nicht bekannt, ob die Methode Dispose IDisposable implementiert.Das liegt daran, dass Sie noch nicht wissen, welche Methoden IDisposable hat.Außerdem wissen Sie nicht einmal, ob IDisposable vorhanden ist, ob es sich um eine Klasse oder Schnittstelle handelt oder wie der vollständige Name lautet.(Ist es System.IDisposable? Oder MyNamespace.IDisposable?)

Um solche Informationen zu erhalten, müssen Sie, wie Sie vermutet haben, auf die semantische Ebene gelangen.

Ich habe keine Möglichkeit gefunden, direkt von einer Methode zur Schnittstelle zu gelangen, es sei denn, es handelt sich um eine explizite Schnittstellenimplementierung (BEARBEITEN: Das liegt daran, dass dies nicht immer möglich ist, siehe Kevins Kommentar).Sie können jedoch von einem Typ zur Implementierung einer bestimmten Schnittstellenmethode gelangen.

Wenn Sie also herausfinden möchten, dass ein bestimmter MethodSymbol IDisposable.Dispose() implementiert, können Sie Folgendes tun:

SyntaxTree unit = SyntaxTree.ParseCompilationUnit(code);

MethodDeclarationSyntax method = …;

var compilation = Compilation.Create("test")
    .AddReferences(new AssemblyFileReference(typeof(object).Assembly.Location))
    .AddSyntaxTrees(unit);

SemanticModel model = compilation.GetSemanticModel(unit);

MethodSymbol methodSymbol = (MethodSymbol)model.GetDeclaredSymbol(method);

var typeSymbol = methodSymbol.ContainingType;

var idisposableDisposeSymbol = model.BindExpression(
    0, Syntax.ParseExpression("System.IDisposable.Dispose()")).Symbol;

var implementation = typeSymbol.FindImplementationForInterfaceMember(
    idisposableDisposeSymbol);

bool methodImplementsDispose = methodSymbol == implementation;

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