我的分析器将匹配具有某些签名的方法。我想从我的分析器内部创建一个我正在分析的类的实例并调用导致分析器启动的方法。
假设源代码处于可编译状态,这可能吗?
获取类名和方法名非常简单,但 Type.GetType(...) 将始终返回 null。
这样做的目的是我希望我的分析器在我使用测试方法并运行它时启动,如果测试失败则失败。
如果代码还没有准备好编译,那么直接返回就可以了。
我的分析器将匹配具有某些签名的方法。我想从我的分析器内部创建一个我正在分析的类的实例并调用导致分析器启动的方法。
假设源代码处于可编译状态,这可能吗?
获取类名和方法名非常简单,但 Type.GetType(...) 将始终返回 null。
这样做的目的是我希望我的分析器在我使用测试方法并运行它时启动,如果测试失败则失败。
如果代码还没有准备好编译,那么直接返回就可以了。
这似乎是可能的,但您需要检查这些解决方案的效率。此外,您不能保证代码是可编译的。
您可以抓取Compilation
对象(假设来自context.SemanticModel.Compilation
),调用Emit
它,然后将其写入磁盘。然后使用Assembly.Load
它来加载它,然后它是简单的反射来实例化你已经知道其名称的类,并使用适当的参数调用它的方法。
另一种方法是Compilation
在脚本会话中使用作为参考程序集,并使用 Roslyn 脚本 API 来调用该方法。上有一个ToMetadataReference
方法Compilation
,所以你可以得到一个MetadataReference
,然后可以传递给ScriptOptions.Default.AddReferences
. 然后您需要将生成的选项实例传递给CSharpScript.EvaluateAsync()
.
还有另一个根本原因是你不能从用户的编译中运行代码,即使它确实编译了——它可能是错误的环境。考虑一个场景,您的目标是 Windows Phone、Xamarin Android/iOS、Linux 上的 .NET Core 或其他。在任何这些情况下,编译器都有可以编译的参考程序集,但显然您不能实际运行该代码,因为它针对的是不同的平台。人们经常问为什么不能将 ITypeSymbol 转换为反射 System.Type 并返回,这就是原因之一——编译器可以在平台 A 上为平台 B 编译代码,但实际上它不能运行(或完全加载)首先 B 的程序集。