是否可以在调用期间获取专用于具体类型的泛型方法的操作和/或语法节点?因此,在下面的示例中,它将是string
而不是T
?
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Semantics;
using System;
using System.Linq;
namespace so
{
internal class Walker : CSharpSyntaxWalker
{
public SemanticModel Model { get; set; }
public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
{
var operation = (IAssignmentExpression)Model.GetOperation(node);
if (operation.Value.Kind == OperationKind.InvocationExpression)
{
var invocation = (IInvocationExpression)operation.Value;
foreach (
var syntax in
invocation.TargetMethod.DeclaringSyntaxReferences.Select(
x => (MethodDeclarationSyntax)x.GetSyntax()))
{
var e = (TypeOfExpressionSyntax)syntax.ExpressionBody.Expression;
Console.WriteLine($"Generic type {invocation.TargetMethod.TypeParameters.First()} specialized with {invocation.TargetMethod.TypeArguments.First()}");
// How to get specialized body here? Currently it is just generic TypeParameters
var symbol = Model.GetSymbolInfo(e.Type).Symbol;
var typeofOperation = (ITypeOfExpression)Model.GetOperation(e);
Console.WriteLine($"{syntax.Identifier.Text} {symbol} {typeofOperation.TypeOperand}");
}
}
base.VisitAssignmentExpression(node);
}
}
internal static class Program
{
private static void Main()
{
var tree = CSharpSyntaxTree.ParseText(@"
public class Program
{
static Type TypeOf<T>() => typeof(T);
public static void Main()
{
Type t;
t = TypeOf<string>();
}
}");
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var compilation = CSharpCompilation.Create(null, new[] { tree }, new[] { mscorlib });
var walker = new Walker { Model = compilation.GetSemanticModel(tree) };
walker.Visit(tree.GetRoot());
}
}
}
输出:
Generic type T specialized with string
TypeOf T T
我正试图在输出中获得TypeOf string string
。
github上的代码 - https://github.com/isanych/so-39447605
答案 0 :(得分:2)
你不能(直接)。
通用类型替换发生在呼叫站点,而不是声明。没有语法树使您的方法体具有替换的T
。
如果你真的想这样做,你需要手动将T
替换为来自呼叫站点的值(并注意各种角落情况,如名称隐藏,从基础类型参数和/或封闭类,重载分辨率,甚至更糟)。