我在使用Roslyn编译为动态程序集时遇到了性能问题。编译大约需要3秒,而使用CodeDom
编译器编译相同代码大约需要300毫秒。以下是我用于编译的代码的精简版本:
var compilation = CSharpCompilation.Create(
"UserPayRules.dll",
syntaxTrees,
assembliesToAdd);
using (var stream = new MemoryStream())
{
stopWatch.Start();
var result = compilation.Emit(stream);
stopWatch.Stop();
Debug.WriteLine("Compilation: {0}", stopWatch.ElapsedMilliseconds);
if (!result.Success)
{
throw new InvalidOperationException();
}
var assembly = Assembly.Load(stream.GetBuffer());
}
这个答案建议将ModuleBuilder对象而不是MemoryStream传递到Emit方法中,以加快速度。我试着遵循这个模式,就像这样:
var compilation = CSharpCompilation.Create(
"UserPayRules.dll",
syntaxTrees,
assembliesToAdd);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("ThisAssembly"),
AssemblyBuilderAccess.RunAndCollect);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("ThisModule");
var result = compilation.Emit(moduleBuilder);
Debug.WriteLine("Compilation: {0}", stopWatch.ElapsedMilliseconds);
if (!result.Success)
{
throw new InvalidOperationException();
}
var assembly = Assembly.Load(stream.GetBuffer());
但我的Roslyn版本显然没有重载Emit
方法,该方法需要ModuleBuilder
。这个版本是:
Id:Microsoft.CodeAnalysis
版本:0.6.4033103-beta(预发布)
项目信息:http://msdn.microsoft.com/en-US/roslyn
显然,这是一个预发布版本,所以api可能发生了更改并不奇怪。然而,
我的问题
- 有人知道为什么
Emit
方法似乎不再有占用ModuleBuilder
的过载吗 - 在仍然使用Roslyn的情况下,有没有其他方法可以更快地进行编译(Roslyn提供了一些优于
CodeDom
和Mono编译器的优势,我不想放弃这些优势)
Roslyn目前并没有公开发出动态程序集的能力。我们删除了它,因为它有问题。
您仍然可以使用Compilation.Emit
API向MemoryStream
发出,然后使用Assembly.Load(byte[])
加载生成的二进制文件。
请注意,在卸载包含的AppDomain
之前,此程序集不会被释放。