使用带有ModuleBuilder而不是MemoryStream的Roslyn Emit方法

Jor*_*ohl 14 c# performance cci dynamic-assemblies roslyn

使用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());
}
Run Code Online (Sandbox Code Playgroud)

这个答案建议将ModuleBuilder对象传递给Emit方法而不是MemoryStream,以加快速度.我试图遵循这种模式,如下:

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());
Run Code Online (Sandbox Code Playgroud)

但我的Roslyn版本显然没有超载的Emit方法需要一个ModuleBuilder.那个版本是:

Id: Microsoft.CodeAnalysis
版本: 0.6.4033103-beta(预发布)
项目信息: http ://msdn.microsoft.com/en-US/roslyn

显然,这是一个预发布,所以api可能已经改变并不奇怪.然而,

我的问题

  1. 有谁知道为什么这个Emit方法似乎不再需要一个超载ModuleBuilder
  2. 还有另一种方法可以让这个编译更快,同时仍然使用Roslyn(Roslyn提供了一些优于CodeDomMono编译器的优点,我不想放弃)?

小智 10

Roslyn目前不公开发射动态组件的能力.我们删除它是因为它有问题.

您仍然可以MemoryStream使用Compilation.EmitAPI 发出,然后使用Assembly.Load(byte[])加载生成的二进制文件.

请注意,在AppDomain卸载包含之前,不会释放此程序集.

  • 若您在罗斯林团队中:请考虑将此信息添加到您的个人资料中,以便您的答案能够脱颖而出. (4认同)
  • 您可能有兴趣投票支持此功能请求:http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/6120992-support-for-collectible-assemblies (2认同)
  • @TomasMatousek你能澄清这究竟是什么"有问题",以及这是否正在为Roslyn提供支持?收藏集已在Reflection.Emit的,因为至少.NET 4.0支持了这样不必编译语法树降到`ModuleBuilder`的能力似乎是在他们的应用程序想要正确的脚本所有用户一个非常理想的目标...... (2认同)