3

私は、遺伝的プログラミング タイプのシナリオで Roslyn API を試してきました。このタイプのプログラミングを行うのに最適な方法のように見えますが、単純なシナリオの実際の実装はそれほど単純ではないように思えます。つまり、この API を適切に使用する方法をよく理解していない可能性があります。これは、実験で変更しようとしている簡単なプログラムです。

string treeText = @"using System;
                                using System.Collections.Generic;

                                namespace TestProgram
                                {
                                    class Program
                                    {
                                        static void Main(string[] args)
                                        {
                                            var myVar = 3;
                                            string myString = ""Hello World"";
                                            List<string> stringList = new List<string>();
                                            Console.WriteLine(myString + myVar);
                                            Console.ReadLine();
                                        }
                                    }
                                }";

SyntaxTree tree = SyntaxTree.ParseText(treeText);

var compilation = Compilation.Create("test.exe",
        syntaxTrees: new[] { tree },
        references: new[]
            {
                new MetadataFileReference(typeof(object).Assembly.Location),
                new MetadataFileReference(typeof(Enumerable).Assembly.Location),
            });

        SemanticModel model = compilation.GetSemanticModel(tree);

簡単な例として、myString インスタンスを使用して新しいメソッド呼び出しを挿入したいと「ランダムに」判断したとします。そのインスタンスからどのメソッドを呼び出すことができるかを把握する効率的な方法は何でしょうか? シンボル情報から必要な MethodInvocationSyntax (使用する特定のメソッドを選択したら) を作成する最良の方法は何でしょうか? SemanticModel クラスで ResolveOverloads というメソッドを見つけましたが、これは必要な場所に表示されますが、このメソッドが必要とするパラメーターへの効率的なパスを見つけるのに苦労しています。それは正しい道ですか?

4

1 に答える 1

1

まず、VariableDeclaratorSyntax変数の を取得します。次に例を示します。

var variable = tree.GetRoot().DescendantNodes()
                   .OfType<VariableDeclaratorSyntax>()
                   .Single(v => v.Identifier.ValueText == "myString");

次に、LocalSymbolからこの変数の を取得しSemanticModelます。

var variableSymbol = (LocalSymbol)model.GetDeclaredSymbol(variable);

次に、そのタイプに基づいて、この変数で呼び出すことができるメソッドのリストを取得できます。インスタンスメソッドであるタイプのすべてのメンバーを単純に取得できます。

var methods =
    variableSymbol.Type.GetMembers()
                  .OfType<MethodSymbol>()
                  .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary);

または、拡張メソッドを含めたい場合は、次を使用できますLookupSymbols()

var methods = model.LookupSymbols(
    variable.GetLocation().SourceSpan.Start, variableSymbol.Type,
    options: LookupOptions.IncludeExtensionMethods)
                   .Where(m => !m.IsStatic);

次に、ロジックに基づいて使用可能なメソッドの 1 つを選択して作成できますInvocationExpressionSyntax(次のコードは、パラメーターなしのメソッドであると想定しています)。

var invocationExpression =
    Syntax.InvocationExpression(
        Syntax.MemberAccessExpression(
            SyntaxKind.MemberAccessExpression,
            Syntax.IdentifierName(variableSymbol.Name),
            (SimpleNameSyntax)Syntax.ParseName(selectedMethod.Name)));

次に、メソッドのどこに式を追加し、その結果をどうするか (もしあれば) を把握する必要があります。

于 2013-05-04T12:17:15.570 に答える