给定SomeInterfaceType
有一个带可选参数的方法:
interface SomeInterface
{
void SomeMethod(int a = 1, string c = "foo",
SomeType e = default, SomeType f = null);
}
SomeInterfaceType = typeof(SomeInterface);
如何从反射类型创建MethodDeclarationSyntax
?
我正在从MethodInfo
中检索参数列表,如下所示:
private ParameterListSyntax GenerateParameterListSyntax(MethodInfo info)
{
var parameters = info.GetParameters();
var parameterList = new SeparatedSyntaxList<ParameterSyntax>();
foreach (var parameter in parameters)
{
var parameterSyntax = SyntaxFactory.Parameter(SyntaxFactory.Identifier(parameter.Name))
.WithType(SyntaxFactory.ParseTypeName(TypeNameOrAlias(parameter.ParameterType)));
if (parameter.IsOptional)
{
parameterSyntax = parameterSyntax.WithDefault( <<< WHAT DO I DO HERE?>>> );
}
parameterList.Add(parameterSyntax);
}
return SyntaxFactory.ParameterList(parameterList);
}
如何自动生成EqualsValueClause
来完成WithDefault
方法?
我在这里留下了SomeInterface
的RoslynQuoter的输出作为参考。
CompilationUnit()
.WithMembers(
SingletonList<MemberDeclarationSyntax>(
InterfaceDeclaration("SomeInterface")
.WithMembers(
SingletonList<MemberDeclarationSyntax>(
MethodDeclaration(
PredefinedType(
Token(SyntaxKind.VoidKeyword)),
Identifier("SomeMethod"))
.WithParameterList(
ParameterList(
SeparatedList<ParameterSyntax>(
new SyntaxNodeOrToken[]{
Parameter(
Identifier("a"))
.WithType(
PredefinedType(
Token(SyntaxKind.IntKeyword)))
.WithDefault(
EqualsValueClause(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(1)))),
Token(SyntaxKind.CommaToken),
Parameter(
Identifier("c"))
.WithType(
PredefinedType(
Token(SyntaxKind.StringKeyword)))
.WithDefault(
EqualsValueClause(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("foo")))),
Token(SyntaxKind.CommaToken),
Parameter(
Identifier("e"))
.WithType(
IdentifierName("SomeType"))
.WithDefault(
EqualsValueClause(
LiteralExpression(
SyntaxKind.DefaultLiteralExpression,
Token(SyntaxKind.DefaultKeyword)))),
Token(SyntaxKind.CommaToken),
Parameter(
Identifier("f"))
.WithType(
IdentifierName("SomeType"))
.WithDefault(
EqualsValueClause(
LiteralExpression(
SyntaxKind.NullLiteralExpression)))})))
.WithSemicolonToken(
Token(SyntaxKind.SemicolonToken))))))
.NormalizeWhitespace()
我不喜欢它,但我得出了这个解决方案:ResolveLiteralExpression
处理parameter.DefaultValue
的下转换。
private ParameterListSyntax GenerateParameterListSyntax(MethodInfo info)
{
var parameters = info.GetParameters();
var parameterList = new List<ParameterSyntax>();
foreach (var parameter in parameters)
{
var parameterSyntax = SyntaxFactory.Parameter(SyntaxFactory.Identifier(parameter.Name))
.WithType(SyntaxFactory.ParseTypeName(TypeNameOrAlias(parameter.ParameterType)));
if (parameter.IsOptional)
parameterSyntax = parameterSyntax.WithDefault(SyntaxFactory.EqualsValueClause(ResolveLiteralExpression(parameter.DefaultValue)));
parameterSyntax = parameterSyntax.WithModifiers(GetModifiers(parameter));
parameterList.Add(parameterSyntax);
}
return SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList<ParameterSyntax>(parameterList));
}
private SyntaxTokenList GetModifiers(ParameterInfo parameter)
{
var tokens = new List<SyntaxToken>();
if (parameter.ParameterType.IsByRef) tokens.Add(SyntaxFactory.Token(parameter.IsOut ? SyntaxKind.OutKeyword : SyntaxKind.RefKeyword));
return SyntaxFactory.TokenList(tokens);
}
private LiteralExpressionSyntax ResolveLiteralExpression(object parameterDefaultValue)
{
switch(parameterDefaultValue)
{
case sbyte n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case byte n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case short n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case ushort n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case int n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case uint n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case long n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case ulong n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case float n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case double n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case decimal n: return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(n));
case string s: return SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(s));
case char c: return SyntaxFactory.LiteralExpression(SyntaxKind.CharacterLiteralExpression, SyntaxFactory.Literal(c));
case bool b: return b
? SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)
: SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression);
case null: return SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression);
default: return SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression);
}
}