16

使用 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 对象传递给 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());

但是我的 Roslyn 版本显然没有Emit采用ModuleBuilder. 那个版本是:

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

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

我的问题

  1. 有谁知道为什么该Emit方法似乎不再具有需要 a 的重载ModuleBuilder
  2. 是否有另一种方法可以在仍然使用 Roslyn 的同时加快编译速度(Roslyn 提供了一些CodeDom我不想放弃的和 Mono 编译器的优势)?
4

1 回答 1

12

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

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

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

于 2014-04-10T01:42:20.460 回答