Roslyn:如何创建泛型方法类型约束

Roslyn: How to create generic method type constraints

我有一些这样的代码(使用 LinqPad):

using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

void Main()
{
    var cd = ClassDeclaration($"TestExtensions")
        .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword));

    var method =
        MethodDeclaration(ParseTypeName($"T"), $"SetTest")
           .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
           .AddTypeParameterListParameters(TypeParameter(Identifier("T")))
           .AddParameterListParameters(
               Parameter(Identifier("definition")).WithType(ParseTypeName("T")).AddModifiers(Token(SyntaxKind.ThisKeyword)),
                Parameter(Identifier("value")).WithType(ParseTypeName("int"))
            )
            .AddConstraintClauses(TypeParameterConstraintClause("T").WithConstraints(GetSL()))
            .WithBody(Block(ParseStatement($"definition.SetField(\"test\", value);"), ParseStatement("return definition;")));

    cd = cd.AddMembers(method);

    // namespace
    var ns = SyntaxFactory
        .NamespaceDeclaration(ParseName("MyNS"))
        .AddMembers(cd);

    var cu = SyntaxFactory.CompilationUnit();

    var code = cu.AddMembers(ns)
        .NormalizeWhitespace()
        .ToFullString();

    // hack because I can't make .WithConstraints work
    //      code = code.Replace("where T :", $"where T : {t.Name}");

    code.Dump();
}

SeparatedSyntaxList<TypeParameterConstraintSyntax> GetSL()
{
    var list = SeparatedList<TypeParameterConstraintSyntax>();
    list.Add(TypeConstraint(ParseTypeName($"Test")));
    return list;
}

除了类型约束之外,它产生了我想要的 例如

namespace MyNS
{
    public static class TestExtensions
    {
        public static T SetTest<T>(this T definition, int value)
            where T :
        {
            definition.SetField("test", value);
            return definition;
        }
    }
}

GetSL().ToFullString() 生成空结果。

我需要类型约束为: where T : Test

到目前为止,我找不到 WithConstraints() 的任何示例。

你几乎得到了正确的结果。 GetSL 方法中的主要问题。因为 SeparatedSyntaxList<TypeParameterConstraintSyntax> 是不可变的,所以您必须使用 Add 方法的 return 值。

该变体有效:

var parameterConstraintClauseSyntax = SyntaxFactory.TypeParameterConstraintClause(
  SyntaxFactory.IdentifierName("T"),
  new SeparatedSyntaxList<TypeParameterConstraintSyntax>()
   .Add(SyntaxFactory.TypeConstraint(SyntaxFactory.ParseTypeName("Test"))));

methodSyntax = methodSyntax.AddConstraintClauses(parameterConstraintClauseSyntax);