Roslyn 通用方法专业化主体

Roslyn generic method specialization body

是否有可能在调用期间为特定于具体类型的泛型方法获取操作 and/or 语法节点?所以在下面的示例中它将是 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

你不能(直接)这样做。

通用类型替换发生在调用点,而不是声明。没有语法树将您的方法体替换为 T.

如果你真的想这样做,你需要手动将 T 替换为来自调用站点的值(并注意各种极端情况,例如名称隐藏、来自 base [= 的类型参数) 18=] 包含 类、重载解析,甚至更糟)。