如何获取特定类型的基本类型

7
我正在开发一个C#代码分析器,并使用Roslyn (.NET编译器API)。我想检查特定类型是否继承自基类类型。例如,假设我们有一组自定义类的层次结构:TypeA-> TypeB-> TypeC-> TypeD,其中TypeA是TypeB的父类,TypeB是TypeC的父类,TypeC是TypeD的父类。我创建了一个方法:
    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 包含需要检查的类型,但这种方法不起作用,因为代码无法获取符号的父类型。

symbol.BaseType 两次返回相同的类类型,然后(在下一次迭代中)我得到 symbol.BaseType 等于 null

expectedParentTypeName 包含完全限定的类型名称:例如 some.namespace.blablabla.TypeC

如何解决这个问题?


更新

如上所述,假设我们有以下继承层级:

TypeA -> TypeB -> TypeC -> TypeD

经过分析,我获得一个具有类型 TypeD 的属性,并且我想检查它是否从 TypeB 继承而来。


更新 #2

TypeA -> TypeB -> TypeC -> TypeD 类型在我编写代码分析器时尚不存在。因此,我不能使用此类类型的 typeof 和其他东西。

它们仅在分析器要工作的上下文中存在。

我的分析器获取源代码的一部分,将其识别为类型名称,并且我想检查该识别的类型名称是否继承自另一个从自定义 nuget 包导入的自定义类型。

我拥有的全部内容 - 我有要分析的源代码,以及类、属性、字段等声明中那些自定义类型的名称。


更新 #3

对于以下代码:

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);

propertyTypeInfoclassTypeInfo中没有包含任何信息。

enter image description here

3个回答

5
  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)


我想我已经想出了如何解决这个任务的方法。感谢您的帮助。 - Novice Student

-1

只是 is

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

谢谢你的帮助,Dave。但是我不使用系统类型,而是使用自定义(非标准)C#类的ITypeSymbol实例。我不确定这种方法在这种情况下是否可行。 - Novice Student

-1

有一些方法(在其他堆栈问题中提到)可以在运行时从类型名称创建对象。(这里有一些有用的代码片段:在c#中使用Type.GetType()返回的类型

然后,您可以获取您的symbol对象并检查它是否是传入的那种类型。

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

Roslyn提供了机制来操作类型和语法树的其他部分,而不必创建处理类的实例。还要注意,处理类型可能会很重/复杂,并且很可能需要将附加对象传递给其构造函数等。谢谢。 - Novice Student

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接