3

I'm using Roslyn to analyze C# code and I've run into an issue when playing around with explicitly implemented interfaces. Given a type that implements an interface, I'm unable to retrieve explicitly implemented members by name. For example:

var tree = CSharpSyntaxTree.ParseText(@"
using System;

namespace ConsoleApplication1
{
    class MyClass : IDisposable
    {
        void IDisposable.Dispose()
        {
        }
        public void Dispose()
        {
        }
    }
}");

var Mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); 
var compilation = CSharpCompilation.Create("MyCompilation",
    syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);

var myType = compilation.GetTypeByMetadataName("ConsoleApplication1.MyClass");
var dispose = myType.GetMembers("Dispose").SingleOrDefault();
//explicitDispose is null.
var explicitDispose = myType.GetMembers("IDisposable.Dispose").SingleOrDefault();

This only seems to be the case when the type lives within a namespace, the following code works fine.

var tree = CSharpSyntaxTree.ParseText(@"
class MyClass : IDisposable
{
    void IDisposable.Dispose()
    {
    }
    public void Dispose()
    {
    }
}");
var Mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); 
var compilation = CSharpCompilation.Create("MyCompilation",
    syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);

var myType = compilation.GetTypeByMetadataName("MyClass");
var dispose = myType.GetMembers("Dispose").SingleOrDefault();
//explicitDispose is not null.
var explicitDispose = myType.GetMembers("IDisposable.Dispose").SingleOrDefault();

Does anyone know why this is occurring? Is there a better way to work with explicitly implemented interfaces?

JoshVarty
  • 9,066
  • 4
  • 52
  • 80

2 Answers2

6

It appears you need to provide the fully qualified method signature when it has been explicitly implemented:

var explicitDispose = myType.GetMembers("System.IDisposable.Dispose").SingleOrDefault();

(I was going to delete this question, but I see someone has marked it as a favorite, so I'll provide the answer that worked for me)

JoshVarty
  • 9,066
  • 4
  • 52
  • 80
  • 3
    There's no harm in answering your own question -- half the point of stack overflow is it's the source of answers for the next person to wonder this! – Jason Malinowski Jun 05 '14 at 22:05
2

Use ITypeSymbol.FindImplementationForInterfaceMethod. These methods are not supposed to be findable "by name".

Neal Gafter
  • 3,293
  • 20
  • 16
  • Actually, this step preceded my use of FindImplementationForInterface(). The issue is I needed to pass in the correct interface member. So I had to first find that member within the interface. I'm basically trying to go from MyClass.System.IDisposable.Dispose() => System.IDisposable.Dispose() – JoshVarty Jun 05 '14 at 22:54
  • That is, given a concrete method, I'm trying to find which interface it was defined in (If it was defined in one at all). – JoshVarty Jun 05 '14 at 22:55
  • The answer you're looking for is not unique, as a method may implement more than one interface method. Iterate through all implemented interface methods of that name and see if its implementation is your method. – Neal Gafter Jun 16 '14 at 23:57