我一直在用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的方法,它出现在我需要结束的地方,但我很难找到该方法所需参数的有效路径。这条路还能走下去吗?
发布于 2013-05-04 20:17:16
首先,获取变量的VariableDeclaratorSyntax,例如:
var variable = tree.GetRoot().DescendantNodes()
.OfType<VariableDeclaratorSyntax>()
.Single(v => v.Identifier.ValueText == "myString");接下来,从SemanticModel获取此变量的LocalSymbol
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);然后,您可以根据您的逻辑选择一个可用的方法并创建InvocationExpressionSyntax (以下代码假设它是一个无参数方法):
var invocationExpression =
Syntax.InvocationExpression(
Syntax.MemberAccessExpression(
SyntaxKind.MemberAccessExpression,
Syntax.IdentifierName(variableSymbol.Name),
(SimpleNameSyntax)Syntax.ParseName(selectedMethod.Name)));然后,您需要确定在方法中的什么位置添加表达式,以及如何处理其结果(如果有的话)。
https://stackoverflow.com/questions/16369487
复制相似问题