5

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

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

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

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

我试图获取方法的声明类型(并检查类型)但没有成功(父属性给我返回 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。那是因为你还不知道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;
于 2012-02-17T22:19:13.277 回答