Roslyn:如果尚未继承自类,如何将泛型类添加到继承的基本列表中?

时间:2018-04-17 20:06:07

标签: c# roslyn roslyn-code-analysis

我有一个命令行应用程序,我从一些字符串输入开始,我正在尝试为实现某个接口的所有类添加一个基类。

我已经到了我所在的部分,并检查了基本列表。但我不确定如何

1)检查以确保该类已经从另一个类继承(在这种情况下什么也不做)。

2)从命令行添加提供的类,以便由相关类继承。

举个例子,说我输入了:

  

-addBaseClass Repository< PocoClass PocoClass 表> -interface IUserRepository

这符合我的班级声明:

internal class UserRepository : IUserRepository
{

现在我希望它像这样:

internal class UserRepository : Repository<User, UserTable>, IUserRepository
{

我获取匹配类的文件并将其加载到Roslyn:

using (var stream = File.OpenRead(filePath))
            {
                syntaxTree = 
  CSharpSyntaxTree.ParseText(SourceText.From(stream), path: filePath);
            }

            var root = syntaxTree.GetRoot();
            //get the initial class declaration
            var classDeclaraction = root.DescendantNodes().OfType<ClassDeclarationSyntax>().FirstOrDefault();
            var baseList = classDeclaraction?.BaseList;

感谢SLaks评论,我能够弄清楚如何添加到基本列表中:

var root = (CompilationUnitSyntax) syntaxTree.GetRoot();
            var classDeclaration = root.DescendantNodes().OfType<ClassDeclarationSyntax>().FirstOrDefault();
            var baseList = classDeclaration?.BaseList;

            var newList = classDeclaration.BaseList.Types.Insert(0, SyntaxFactory.SimpleBaseType(
                SyntaxFactory.GenericName(
                        SyntaxFactory.Identifier(baseClass))
                    .WithTypeArgumentList(
                        SyntaxFactory.TypeArgumentList(
                            SyntaxFactory.SeparatedList<TypeSyntax>(GetGenericParameterSyntaxNode(genericParameters))))).NormalizeWhitespace());
            var modifierList = classDeclaration.Modifiers.Replace(classDeclaration.Modifiers.FirstOrDefault(x => x.Kind() == SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.InternalKeyword));
            var newDeclaration = classDeclaration.WithModifiers(modifierList).WithBaseList(SyntaxFactory.BaseList(newList)).NormalizeWhitespace();

            var newDeclarationRoot = SyntaxFactory.CompilationUnit()
                .WithMembers(SyntaxFactory.SingletonList<MemberDeclarationSyntax>(newDeclaration)).NormalizeWhitespace();
            var updatedRoot = root.ReplaceNode(root.FindNode(classDeclaration.Span), newDeclarationRoot.FindNode(newDeclaration.Span)).NormalizeWhitespace();

所以我现在正在从updatedRoot生成文件。但仍不确定如何检查该类是否已从类继承。 BaseList包含接口和继承的类,我似乎无法在对象图中找到任何区别的东西。

1 个答案:

答案 0 :(得分:0)

要查明类声明是否继承了一个类,你可以使用:

if (classDeclaration.BaseList.Types.TryFirst(out var baseType) &&
    semanticModel.GetSymbolInfo(baseType.Type).Symbol is ITypeSymbol type &&
    type.TypeKind == TypeKind.Class)
{
}

使用SyntaxGenerator添加基类型可能最简单:

var updated = syntaxGenerator.AddBaseType(
    classDeclaration,
    SyntaxFactory.ParseName("Repository<User, UserTable>"));

语法生成器为C#执行此操作:

var updated = classDeclaration.WithBaseList(
    classDeclaration.BaseList.WithTypes(
        classDeclaration.BaseList.Types.Insert(
            0,
            SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseName("Repository<User, UserTable>")))));

here省略检查上面的空列表。