简体   繁体   中英

Using Roslyn Emit method with a ModuleBuilder instead of a MemoryStream

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)?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM