使用Roslyn确定类是否为记录

问题描述

我正在编写一个代码生成器,并且需要知道我在Microsoft.CodeAnalysis中添加功能的类是否是记录。

我可以通过切换到语法模型来做到这一点,就像这样:

public static bool IsRecord(this ITypeSymbol type)
{
    if (type == null || type.TypeKind != TypeKind.Class)
        return false;
    bool isRecord = (type.DeclaringSyntaxReferences.Any(x => (x.SyntaxTree.GetRoot().FindNode(x.Span) is RecordDeclarationSyntax)));
    return isRecord;
}

但是有没有办法用语义模型来做到这一点?我可能会遗漏一些显而易见的东西,但是我检查了在我看来是显而易见的地方,并且还在github上进行了搜索。似乎在罗斯林(Roslyn)内有一个internal IsRecord,但我找不到任何公开的东西。如果我无法在语义模型中访问此代码,那么即使该类型是从另一个程序集导入的代码中获得的,上述方法也可以工作吗?

解决方法

从 Roslyn API 的 3.9.0-2.final 版本(这对应于 Visual Studio 16.9 预览版 2)开始,ITypeSymbol 现在具有您可以使用的 IsRecord 属性。

,

似乎没有任何官方公共财产IsRecord。因此,我们只需要查找记录将包含的内容,例如一个隐式声明的名为“ EqualityContract”的属性:

type.GetMembers().Any(x => x.Kind == SymbolKind.Property && x.Name == "EqualityContract" && x.IsImplicitlyDeclared)