给定MethodDeclarationSyntax对象,如何找出方法的声明类型?
我的实际问题是我需要弄清楚引用的方法是否正在实现接口方法。
例如,给定下面的代码,如果我有 Dispose()方法的MethodDeclarationSyntax,那么如何判断它是IDisposable.Dispose()的实现?
using System;
abstract class InterfaceImplementation : IDisposable
{
public abstract void Dispose();
}
我试图获取方法的声明类型(并检查类型)但没有成功(Parent属性让我回到InterfaceImplementation类)。
我也试图抓住方法的语义符号:
var methodSymbol = (MethodSymbol) semanticModel.GetDeclaredSymbol(methodDeclaration);
但无法发现任何可以帮助我的事情。
想法?
答案 0 :(得分:7)
获得方法符号后,您可以询问给定方法是否在给定类型中实现接口方法。代码很简单:
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”,并且具有IDIisposable的派生类型的InterfaceImplementation,那么Dispose()方法仍然可以实现它。
答案 1 :(得分:4)
语法类型(如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;