查找方法的声明类型

Vag*_*aus 5 .net c# roslyn

给定MethodDeclarationSyntax对象,如何找出方法的声明类型?

我的实际问题是我需要弄清楚引用的方法是否正在实现接口方法.

例如,给定下面的代码,如果我有Dispose()方法的MethodDeclarationSyntax ,那么如何判断它是IDisposable.Dispose()的实现?

using System;
abstract class InterfaceImplementation : IDisposable
{
    public abstract void Dispose();
}
Run Code Online (Sandbox Code Playgroud)

我试图获取方法的声明类型(并检查类型)没有成功(Parent属性给我回到InterfaceImplementation类).

我也试图抓住方法的语义符号:

var methodSymbol = (MethodSymbol) semanticModel.GetDeclaredSymbol(methodDeclaration);
Run Code Online (Sandbox Code Playgroud)

但无法发现任何可以帮助我的东西.

想法?

Jas*_*ski 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));
Run Code Online (Sandbox Code Playgroud)

重要的是要注意这假设包含Dispose方法的类型是声明它实现IDisposable的类型.在C#中,一个方法可以实现一个仅在派生类型上声明的接口方法.更具体地说,如果您在上面的代码中省略了":IDisposable",并且具有IDIisposable的派生类型的InterfaceImplementation,那么Dispose()方法仍然可以实现它.


svi*_*ick 5

语法类型(如MethodDeclarationSyntax在语法级别上运行。在此级别上,不知道该方法是否Dispose实现IDisposable。那是因为您还不知道有什么方法IDisposable。而且,您甚至都不知道是否IDisposable存在,是类还是接口或它的全名是什么。(是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;
Run Code Online (Sandbox Code Playgroud)

  • 您不能从方法中执行此操作的原因是有时您无法分辨。如果你有`class Base { public void Dispose() } class Derived : Base, IDisposable { }` 那么“Dispose”是实现_如果你有一个Derived_的实例,但如果你有一个Base的实例则不是...... (2认同)