简体   繁体   English

Roslyn CTP - 随机码修改

[英]Roslyn CTP - Random Code Modification

I have been experimenting with the Roslyn API in a genetic programming type of scenario. 我一直在遗传编程类型的场景中试验Roslyn API。 It appears like a great way to do that type of programming, but the actual implementation of simple scenarios doesn't seem very straightforward, which means I probably don't have a good understanding of how to use this API properly. 这似乎是一种很好的方式来进行这种类型的编程,但是简单场景的实际实现似乎并不是非常简单,这意味着我可能对如何正确使用此API没有很好的理解。 Here is a simple program I am trying to modify in my experiments: 这是我试图在我的实验中修改的一个简单程序:

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);

Just as a simple example let's say I somehow "randomly" decided I want to insert a new method invocation using the myString instance. 就像一个简单的例子,让我说我以某种方式“随机”决定我想使用myString实例插入一个新的方法调用。 What would be an efficient way to figure out what methods I could invoke off of that instance? 什么是一种有效的方法来确定我可以从该实例调用哪些方法? What would then be the best way to create the necessary MethodInvocationSyntax (once I chose a specific method to use) from the symbol information? 那么从符号信息中创建必要的MethodInvocationSyntax(一旦我选择使用特定方法)的最佳方法是什么? I found a method called ResolveOverloads on the SemanticModel class which appears where I need to end up, but I am having some difficulty figuring out an efficient path to the parameters this method requires. 我在SemanticModel类上找到了一个名为ResolveOverloads的方法,它出现在我需要结束的地方,但是我很难找到这个方法所需参数的有效路径。 Is that even the right path to go down? 这甚至是正确的道路吗?

First, get the VariableDeclaratorSyntax for your variable, for example: 首先,获取VariableDeclaratorSyntax ,例如:

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

Next, get the LocalSymbol for this variable from the SemanticModel : 接下来,从SemanticModel获取此变量的LocalSymbol

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

Then you can get a list of methods you can invoke on this variable based on its type. 然后,您可以根据其类型获取可以在此变量上调用的方法列表。 You can either simply get all members of the type that are instance methods: 您可以简单地获取该类型的所有成员作为实例方法:

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

Or, if you wanted to include extension methods, you could use LookupSymbols() : 或者,如果要包含扩展方法,可以使用LookupSymbols()

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

You can then choose one of the available methods based on your logic and create InvocationExpressionSyntax (the following code assumes it's a parameterless method): 然后,您可以根据逻辑选择一种可用方法,并创建InvocationExpressionSyntax (以下代码假定它是无参数方法):

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

You would then need to figure out where in your method to add the expression and what to do with its result (if anything). 然后,您需要确定在方法中添加表达式的位置以及如何处理其结果(如果有的话)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM