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

C# Roslyn:如果尚未从类继承,如何将泛型类添加到继承的基列表中?,c#,roslyn,roslyn-code-analysis,C#,Roslyn,Roslyn Code Analysis,我有一个命令行应用程序,从一些字符串输入开始,我试图向实现某个接口的所有类添加一个基类 我已经到了上课的地方,检查了基本列表。但我不知道该怎么做 1) 检查以确保该类尚未从另一个类继承(在这种情况下,不执行任何操作) 2) 从命令行添加所提供的类,以由相关类继承 例如,假设我输入: -addBaseClass存储库-接口IUserRepository 这将与我的类声明相匹配: internal class UserRepository : IUserRepository { 现在我希望它是这样

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

我已经到了上课的地方,检查了基本列表。但我不知道该怎么做

1) 检查以确保该类尚未从另一个类继承(在这种情况下,不执行任何操作)

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

例如,假设我输入:

-addBaseClass存储库-接口IUserRepository

这将与我的类声明相匹配:

internal class UserRepository : IUserRepository
{
现在我希望它是这样的:

internal class UserRepository : Repository<User, UserTable>, IUserRepository
{
内部类UserRepository:Repository,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;
使用(var stream=File.OpenRead(filePath))
{
合成树=
CSharpSyntaxTree.ParseText(SourceText.From(stream),路径:filePath);
}
var root=syntaxTree.GetRoot();
//获取初始类声明
var classDeclaraction=root.degenantNodes().OfType().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();
var root=(CompilationUnitSyntax)syntaxTree.GetRoot();
var classDeclaration=root.degenantNodes().OfType().FirstOrDefault();
var baseList=classDeclaration?.baseList;
var newList=classDeclaration.BaseList.Types.Insert(0,SyntaxFactory.SimpleBaseType(
SyntaxFactory.GenericName(
SyntaxFactory.Identifier(基类))
.WithTypeArgumentList(
SyntaxFactory.TypeArgumentList(
SeparatedList(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(newDeclaration)).NormalizeWhitespace();
var updatedRoot=root.ReplaceNode(root.FindNode(classDeclaration.Span),newDeclarationRoot.FindNode(newDeclaration.Span)).NormalizeWhitespace();

因此,我现在可以从UpdateRoot生成文件了。但是仍然不确定如何检查类是否已经从类继承。基列表包括接口和继承的类,我似乎在对象图中找不到任何区别。

用于确定类声明是否继承了可以使用的类:

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>"));
var updated=syntaxGenerator.AddBaseType(
类别声明,
ParseName(“存储库”);
语法生成器为C#执行此操作:

var updated=classDeclaration.WithBaseList(
classDeclaration.BaseList.WithTypes(
classDeclaration.BaseList.Types.Insert(
0,
SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseName(“Repository”;));

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

您应该为类和参数创建标记,而不是组装字符串。用于帮助。这太棒了!我现在可以知道如何使用该页面添加到基列表中。但我仍然不确定如何检查现有基列表以查看它是否已继承类。重新创建是否正常ld整个编译单元?似乎我必须遍历,直到我有了MemberDeclarationSyntax,这样我才能有一个根来获取最终替换的节点。是否无法仅替换基列表,请将其粘贴在某些东西中,以便我可以从中获取替换的节点?更新的问题。您需要语义模型。
var updated = classDeclaration.WithBaseList(
    classDeclaration.BaseList.WithTypes(
        classDeclaration.BaseList.Types.Insert(
            0,
            SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseName("Repository<User, UserTable>")))));