将Roslyn Emit方法与ModuleBuilder一起使用,而不是使用MemoryStream



我在使用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可能发生了更改并不奇怪。然而,

我的问题

  1. 有人知道为什么Emit方法似乎不再有占用ModuleBuilder的过载吗
  2. 在仍然使用Roslyn的情况下,有没有其他方法可以更快地进行编译(Roslyn提供了一些优于CodeDom和Mono编译器的优势,我不想放弃这些优势)

Roslyn目前并没有公开发出动态程序集的能力。我们删除了它,因为它有问题。

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

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

相关内容

  • 没有找到相关文章

最新更新