Roslyn从IMethodSymbol获取MethodInfo

时间:2015-05-29 11:33:42

标签: c# .net reflection roslyn methodinfo

如何从IMethodSymbol(Roslyn语法树)中可靠地获取MethodInfo(反射)。我可以从IMethodSymbol获取Type,并且该类型有许多方法,其中一个方法与IMethodSymbol实例匹配。

e.g。

int i = 0;
i.Equals(5);

IMethodSymbol标识'等于'

注意[Int32]类型有2个[Equals]方法,一个采用[Object],另一个采用[Int32]参数。

我正在解析脚本,我没有任何工作区实例。

有什么想法吗? 斯特沃

1 个答案:

答案 0 :(得分:1)

无法从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来分析某些脚本那么你可能没有那个限制。