Using Roslyn Emit method with a ModuleBuilder instead of a MemoryStream

隐身守侯 提交于 2019-11-27 23:27:27

问题


I was having trouble with performance when using Roslyn to compile to a dynamic assembly. Compilation was taking ~3 seconds, compared to ~300 milliseconds to compile the same code when using the CodeDom compiler. Here's a pared-down version of the code I'm using to do the compilation:

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());
}

This answer suggests passing a ModuleBuilder object into the Emit method instead of a MemoryStream in order to speed things up. I tried to follow that pattern, like so:

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());

But my version of Roslyn apparently doesn't have an overload of the Emit method that takes a ModuleBuilder. That version is:

Id: Microsoft.CodeAnalysis
Version: 0.6.4033103-beta (Prerelease)
Project Information: http://msdn.microsoft.com/en-US/roslyn

Obviously, this is a prerelease, so it's not strange that the api might have changed. However,

My Question(s)

  1. Does anyone know why the Emit method no longer seems to have an overload that takes a ModuleBuilder?
  2. Is there another way to make this compilation faster while still using Roslyn (Roslyn offers a couple advantages over the CodeDom and Mono compilers that I'd prefer not to give up)?

回答1:


Roslyn currently doesn't expose ability to emit dynamic assemblies. We removed it because it was problematic.

You can still emit to a MemoryStream using Compilation.Emit APIs and then use Assembly.Load(byte[]) to load the resulting binary.

Note that this assembly won't be freed until the containing AppDomain is unloaded.



来源:https://stackoverflow.com/questions/22974473/using-roslyn-emit-method-with-a-modulebuilder-instead-of-a-memorystream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!