Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting type from a symbol in roslyn

What is the best general purpose way to get a System.Type from Microsoft.CodeAnalysis.ISymbol for different types of symbols ? (e.g. class declarations, variable, properties, etc)

I want to be able to do various checks on the type e.g. as checking if the type implements any interface or is cast-able to any interface, just like one can check on System.Type.

The problem I am having is that most of the concrete classes used to represent the symbol are internal (see http://sourceroslyn.io/) and I could not find tye type information in the ISymbol.

  • SourceNamedTypeSymbol
  • LocalSymbol

I retrieve the ISymbol using the following code

var objectSymbol = (ISymbol)model.GetDeclaredSymbol(obj.Node);
like image 371
antiskidwarpdrive Avatar asked Jan 12 '16 15:01

antiskidwarpdrive


2 Answers

Short answer: you can't. There is no proper way to get a System.Type (reflection) from an ISymbol (Roslyn).

One option to do go in the direction you want is constructing the fully-qualified name of your type and then looking that up through reflection (example).

You should probably ask yourself whether this is something you need to do in the first place though -- reflection and Roslyn aren't really intended to work together.

What you are interested in, however, can be done through Roslyn as well. The key here is using the semantic model which has all this information for you. All declarations (opposed to usages) have a specific overload available that allows you to get the declaring symbol and return it in the appropriate type (such as INamedTypeSymbol in this case).

Take the following example:

const string source = @"
using System;

namespace MyNamespace 
{
    class MyClass : IDisposable
    {
        void Method()
        {
            MyClass nameOfVariable, another;
        }
    }
}
";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CSharpCompilation.Create("MyCompilation", new[] { tree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
var semanticModel = compilation.GetSemanticModel(tree);
var root = tree.GetRoot();

var classSymbol = semanticModel.GetDeclaredSymbol(root.DescendantNodes().OfType<ClassDeclarationSyntax>().First());
Console.WriteLine(string.Join(", ", classSymbol.AllInterfaces));

This will display all the interfaces the class implements. Keep in mind however that this just refers to the current definition -- if you're also interested in base types you'll have to go through the hierarchy yourself.

In your scenario you should be able to just cast it to the right type (assuming you are checking a declaration node):

var objectSymbol = (INamedTypeSymbol) model.GetDeclaredSymbol(obj.Node);
like image 168
Jeroen Vannevel Avatar answered Nov 19 '22 15:11

Jeroen Vannevel


I think this is what you are looking for:

var castedProperty = (IPropertySymbol) property;
var type = castedProperty.Type.Name;

The variable 'property' is an ISymbol instance.

like image 2
Rodrigo Jacques Avatar answered Nov 19 '22 16:11

Rodrigo Jacques