2016-09-12 21 views
0

呼び出し中に具体的なタイプに特化した汎用メソッドの演算および/または構文ノードを取得することは可能ですか?したがって、下のサンプルではTの代わりにstringになりますか?Roslyn汎用メソッドの特殊化本体

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

答えて

2

あなたは(直接)を行うことはできません。

汎用タイプの置換は、宣言ではなく、コールサイトで行われます。置換されたTのメソッド本文を持つ構文ツリーはありません。

実際にそれを行うには、Tをcallsiteの値で手動で置き換える必要があります(名前の非表示、ベースクラスからのパラメータの入力、オーバーロード解像度、および悪化)。

+0

はい、代入は呼び出し時に発生します。そのため、この情報を呼び出し式で取得しようとしています。手動で置換を実行するのは、多くの作業ですが、Roslynは特別な機能のためにILを生成していますが、私は実際に同じ作業をしたくありません:) – ISanych

+0

これは.NETのジェネリックスの仕組みではありません。 ILには、ジェネリック関数のバージョンは1つしかなく、特殊な関数はありません。 – svick

+0

あなたは正しいです、私は混乱しています。私は、特殊なクラスは異なるタイプであり、そこでもメソッドが異なると仮定しています。私はまだそれが当てはまると思いますが、これらの特殊なメソッドを作成するのはJITです。 ILは一度だけ生成されるので、必要なレベルの詳細ですべての操作を取得することが可能でなければなりません。ですから、SLaksが指摘しているように、まだ特殊な実装ではすべてのシンボルを解決する必要があります。私はこのトピックを研究する必要があります。 – ISanych

関連する問題