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);
我有一些这样的代码(使用 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);