C# Roslyn CTP-随机码修改

C# Roslyn CTP-随机码修改,c#,genetic-programming,roslyn,C#,Genetic Programming,Roslyn,我一直在基因编程类型的场景中试验Roslyn API。这似乎是一种很好的编程方式,但简单场景的实际实现似乎并不简单,这意味着我可能对如何正确使用此API没有很好的理解。下面是我在实验中尝试修改的一个简单程序: string treeText = @"using System; using System.Collections.Generic; namespace Te

我一直在基因编程类型的场景中试验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);
stringtreetext=@”使用系统;
使用System.Collections.Generic;
名称空间测试程序
{
班级计划
{
静态void Main(字符串[]参数)
{
var-myVar=3;
字符串myString=”“Hello World”“;
List stringList=新列表();
Console.WriteLine(myString+myVar);
Console.ReadLine();
}
}
}";
SyntaxTree-tree=SyntaxTree.ParseText(treeText);
var compilation=compilation.Create(“test.exe”,
syntaxTrees:new[]{tree},
参考文献:新[]
{
新的MetadataFileReference(typeof(object).Assembly.Location),
新的MetadataFileReference(typeof(Enumerable).Assembly.Location),
});
SemanticModel model=compilation.GetSemanticModel(树);

作为一个简单的例子,假设我以某种方式“随机”决定使用myString实例插入一个新的方法调用。找出我可以从该实例调用哪些方法的有效方法是什么?那么,从符号信息创建必要的MethodInvocationSyntax(一旦我选择了要使用的特定方法)的最佳方法是什么?我在SemanticModel类上找到了一个名为ResolveOverloads的方法,它出现在我需要结束的地方,但我很难找到该方法所需参数的有效路径。这是正确的路径吗?

首先,获取变量的
VariableDeclaratorSyntax
,例如:

var variable = tree.GetRoot().DescendantNodes()
                   .OfType<VariableDeclaratorSyntax>()
                   .Single(v => v.Identifier.ValueText == "myString");
然后,您可以根据该变量的类型获取可以对此变量调用的方法列表。您可以简单地获取属于实例方法的类型的所有成员:

var methods =
    variableSymbol.Type.GetMembers()
                  .OfType<MethodSymbol>()
                  .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary);
然后,您可以根据逻辑选择一种可用方法,并创建
InvocationExpressionSyntax
(以下代码假定它是一种无参数方法):


然后,您需要确定在方法中的何处添加表达式以及如何处理其结果(如果有)。

再次感谢svick!我将在这里用您的答案中的代码进行实验,看看是否可以回答我自己关于添加带参数的方法的问题。如果我对ResolveOverloads方法仍然有困难,那么我将发布一个新的问题。提示:您应该始终使用LookupSymbols来处理类似的问题,因为您还需要确保在调用站点可以访问该方法。LookupSymbols可以做到这一点,而GetMembers不能做到。
var methods =
    variableSymbol.Type.GetMembers()
                  .OfType<MethodSymbol>()
                  .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary);
var methods = model.LookupSymbols(
    variable.GetLocation().SourceSpan.Start, variableSymbol.Type,
    options: LookupOptions.IncludeExtensionMethods)
                   .Where(m => !m.IsStatic);
var invocationExpression =
    Syntax.InvocationExpression(
        Syntax.MemberAccessExpression(
            SyntaxKind.MemberAccessExpression,
            Syntax.IdentifierName(variableSymbol.Name),
            (SimpleNameSyntax)Syntax.ParseName(selectedMethod.Name)));