5

MethodDeclarationSyntaxオブジェクトが与えられた場合、メソッドの宣言型をどのように見つけることができますか?

私の実際の問題は、参照されるメソッドがインターフェースメソッドを実装しているかどうかを把握する必要があることです。

たとえば、次のコードを考えると、Dispose()メソッドのMethodDeclarationSyntaxがある場合、IDisposable.Dispose()の実装であるとどのように結論付けることができますか?

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

メソッドの宣言型を取得しようとしました(そして型をチェックしました)が成功しませんでした(ParentプロパティはInterfaceImplementationクラスを返します)。

また、メソッドのセマンティックシンボルを取得しようとしました。

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

しかし、私を助けることができるものを見つけることができませんでした。

アイデア?

4

2 に答える 2

8

メソッドシンボルを取得したら、特定のメソッドが特定のタイプ内にインターフェイスメソッドを実装しているかどうかを確認できます。コードはかなり単純です:

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

これは、Disposeメソッドを含むタイプが、IDisposableを実装することを示すタイプであると想定していることに注意することが重要です。C#では、メソッドが派生型でのみ記述されているインターフェイスメソッドを実装することが可能です。より具体的には、上記のコードで「:IDisposable」を省略し、IDisposableである派生型のInterfaceImplementationがあった場合でも、そのDispose()メソッドはそれを実装できます。

于 2012-02-17T22:19:55.520 に答える
5

構文タイプ(などMethodDeclarationSyntax)は、構文レベルでのみ機能します。このレベルでは、メソッドがをDispose実装するかどうかはわかりませんIDisposable。それは、メソッドが何であるかをまだ知らないためですIDisposableIDisposableさらに、存在するかどうか、それがクラスかインターフェースか、またはそのフルネームが何であるかさえわかりません。(それはSystem.IDisposable?またはMyNamespace.IDisposable?)

そのような情報を取得するには、ご想像のとおり、セマンティックレベルに到達する必要があります。

明示的なインターフェイスの実装でない限り、メソッドからインターフェイスに直接アクセスする方法は見つかりませんでした(編集:常に可能であるとは限らないためです。Kevinのコメントを参照してください)。ただし、タイプから特定のインターフェイスメソッドの実装に移行することはできます。

MethodSymbolしたがって、特定の実装を知りたい場合は、次のIDisposable.Dispose()ようにすることができます。

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;
于 2012-02-17T22:19:13.277 に答える