如何从IMethodSymbol (Roslyn语法树)可靠地获得MethodInfo(反射)。我可以从IMethodSymbol中获得Type,这个类型有很多方法,其中一个方法与IMethodSymbol实例匹配。
。
int i = 0;
i.Equals(5);
IMethodSymbol标识'Equals'的地方
注意,在[Int32]类型上有2个[Equals]方法,一个接受[Object]参数,另一个接受[Int32]参数。
我正在解析脚本,我没有任何工作空间实例。
任何想法?Stevo
不可能可靠地从IMethodSymbol中获取MethodInfo,因为您需要加载包含该方法所在类型的程序集,这可能是正在解析的脚本的情况,但可能不是是执行分析的代码的情况。
换句话说,你正在运行的脚本代码可能已经加载了汇编X,它包含了类型T,其中有方法M(因此脚本代码可以有调用方法M的代码)但是分析器可能没有加载汇编X所以它可以不加载类型T所以它可以不获取方法M的MethodInfo实例
然而,对于像System这样的程序集,您可以从分析器代码访问它可能是相当安全的。
所以,你需要做的就是获取具有该方法的类型的命名空间和类型名,并获取它的TypeInfo实例。然后使用GetMethod -传递方法的名称和参数类型来获得MethodInfo。像这样:
var invocation = (InvocationExpressionSyntax)context.Node;
var methodSymbol = (IMethodSymbol)context.SemanticModel.GetSymbolInfo(invocation).Symbol;
var declaringTypeName = string.Format(
"{0}.{1}",
methodSymbol.ContainingType.ContainingAssembly.Name,
methodSymbol.ContainingType.Name
);
var methodName = methodSymbol.Name;
var methodArgumentTypeNames = methodSymbol.Parameters.Select(
p => p.Type.ContainingNamespace.Name + "." + p.Type.Name
);
var methodInfo = Type.GetType(declaringTypeName).GetMethod(
methodName,
methodArgumentTypeNames.Select(typeName => Type.GetType(typeName)).ToArray()
);
值得注意的是,分析器通常是可移植的类库,不能访问完整的反射API(这意味着上面的代码不能工作),但如果你只是在一个项目中使用Roslyn来分析一些脚本,那么你可能不需要有这个限制。