Finding a method's declaring type
Question
Given a MethodDeclarationSyntax object how can I find out the method's declaring type?
My actual problem is that I need to figure it out whether the referenced method is implementing an interface method or not.
For instance, given the code bellow, if I have a MethodDeclarationSyntax for the Dispose() method, how can conclude it is the implementation of the IDisposable.Dispose()?
using System;
abstract class InterfaceImplementation : IDisposable
{
public abstract void Dispose();
}
I've tried to get the method's declaring type (and check the type) with no success (Parent property gives me back InterfaceImplementation class).
I also have tried to grab the semantic symbol for the method:
var methodSymbol = (MethodSymbol) semanticModel.GetDeclaredSymbol(methodDeclaration);
but could not spot anything that could help me.
Ideas?
Solution
Once you have the method symbol, you can ask if a given method is implementing an interface method within a given type. The code is fairly simple:
MethodSymbol method = ...;
TypeSymbol type = method.ContainingType;
MethodSymbol disposeMethod = (MethodSymbol)c.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single();
bool isDisposeMethod = method.Equals(type.FindImplementationForInterfaceMember(disposeMethod));
It's important to note this assumes the type that contains the Dispose method is the type that states it implements IDisposable. In C#, it's possible for a method to implement an interface method that's only stated on a derived type. More concretely, if you ommtted the ": IDisposable" on your code above, and had a derived type of InterfaceImplementation that was IDisposable, that Dispose() method can still implement it.
OTHER TIPS
The syntax types (like MethodDeclarationSyntax
) operate only on the syntactic level. At this level, there is no knowledge whether the method Dispose
implements IDisposable
. That's because you don't know yet what methods IDisposable
has. What's more, you don't even know whether IDisposable
exists, whether it's a class or interface, or what is its full name. (Is it System.IDisposable
? Or MyNamespace.IDisposable
?)
To get information like that, you need to get to the semantic level, as you guessed.
I didn't find any way to get from a method to the interface directly, unless it's an explicit interface implementation (EDIT: that's because it's not always possible, see Kevin's comment). But you can get from a type to the implementation of some specific interface method.
So, if you want to find out that a certain MethodSymbol
implements IDisposable.Dispose()
, you could do something like:
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;