Novice Student
Novice Student

Reputation: 147

How to get base type for the particular type

I am working on a C# code analyzer and use Roslyn (.NET Compiler API).

And I would like to check, that a particular type is inherited from a base class type.

For example, let's assume we have a hierarchy of custom classes:

TypeA -> TypeB -> TypeC -> TypeD

Where TypeA is parent class for TypeB, TypeB is parent for TypeC and TypeC is parent for TypeD.

I created a method:

    bool InheritsFrom(ITypeSymbol symbol, string expectedParentTypeName)
    {
        while (true)
        {
            if (symbol.ToString().Equals(expectedParentTypeName))
            {
                return true;
            }

            if (symbol.BaseType != null)
            {
                symbol = symbol.BaseType;
                continue;
            }
            break;
        }

        return false;
    }

symbol contains the type, that should be checked. But this approach does not work. Code does not get the parent type for the symbol.

symbol.BaseType returns the same class type twice and then (on the next iteration) I get symbol.BaseType equal to null.

expectedParentTypeName contains fully qualified type name: for example some.namespace.blablabla.TypeC

How can I solve this task?


Update

As I noted above, let's assume we have a hierarchy:

TypeA -> TypeB -> TypeC -> TypeD

Upon analysis I get a property with type TypeD and I want to check, that it is inherited from TypeB


Update #2

TypeA -> TypeB -> TypeC -> TypeD types are not existing yet when I write my code analyser. So, I can't use typeof and other stuff for these types.

They will exist only in context the analyzer will work in.

My analyzer gets a part of the source code, recognizes it as a type name and I want to check, that this recognized type name is inherited from another custom type, imported from a custom nuget package.

All I have - I have source code to analyze and names of those custom types in class, property, field, etc declarations.


Update #3

For the following code:

SyntaxNodeAnalysisContext context; // is already initialized 

PropertyDeclarationSyntax propertyDeclaration = (PropertyDeclarationSyntax)context.Node;

ClassDeclarationSyntax classDeclaration = (ClassDeclarationSyntax) propertyDeclaration.Parent;

TypeInfo propertyTypeInfo = context.SemanticModel.GetTypeInfo(propertyDeclaration);

TypeInfo classTypeInfo = context.SemanticModel.GetTypeInfo(classDeclaration);

propertyTypeInfo and classTypeInfo do not contain any information inside.

enter image description here

Upvotes: 7

Views: 2910

Answers (3)

George Alexandria
George Alexandria

Reputation: 2936

  1. ITypeSymbol.BaseType is exactly that you need to retrieve the base type. BaseType can be null if your type is System.Object, interface or pointer type, also if you have a couple of troubles with semantic logic in your Compilation it can be a error type, which mean you miss something reference and Roslyn cannot corectly resolve a types. In other case symbol.BaseType should work very well by default. So I sugges you to check your symbol and check diagnostics in Compilation

  2. ITypeSymbol.ToString() will return string that would be constructed by CSharpErrorMessageFormat, which has FQN type style that is enough for your question. If you would a more, you can pass a custom SymbolDisplayFormat to ToDisplayString

  3. For declaration nodes SemanticModel.GetTypeInfo will returns the null TypeSymbol and ConvertedSymbol by design, instead of this you should use SemanticModel.GetDeclaredSymbol

    var propertyTypeSymbol = context.SemanticModel.GetDeclaredSymbol(propertyDeclaration) as ITypeSymbol;
    var classTypeSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration) as ITypeSymbol;
    

    P.S. be carefull, to use GetDeclaredSymbol for some special declaration nodes: for example FieldDeclarationSyntax)

Upvotes: 5

SazooCat
SazooCat

Reputation: 170

There are ways (referred to in other stack questions) to create an object from a typename at runtime. (There are some useful code snippets in here: using type returned by Type.GetType() in c#)

You could then get an object of your symbol and check if it is of that type passed in.

if (symbolObject is typeClassWorkedOutAbove)
{
    //do stuff
}

Upvotes: -1

Dave Bish
Dave Bish

Reputation: 19646

Just is ?

if(DerivedType is BaseType)
{
    //Party time
}

Upvotes: -1

Related Questions