Roslyn泛型方法专业化主体

时间:2016-09-12 09:49:15

标签: c# generics roslyn

是否可以在调用期间获取专用于具体类型的泛型方法的操作和/或语法节点?因此,在下面的示例中,它将是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

1 个答案:

答案 0 :(得分:2)

你不能(直接)。

通用类型替换发生在呼叫站点,而不是声明。没有语法树使您的方法体具有替换的T

如果你真的想这样做,你需要手动将T替换为来自呼叫站点的值(并注意各种角落情况,如名称隐藏,从基础类型参数和/或封闭类,重载分辨率,甚至更糟)。