使用罗斯林的Emit方法用一个ModuleBuilder,而不是一个MemoryStream [英] Using Roslyn Emit method with a ModuleBuilder instead of a MemoryStream

查看:421
本文介绍了使用罗斯林的Emit方法用一个ModuleBuilder,而不是一个MemoryStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是用罗斯林编译到一个动态组装时具有的性能麻烦。编译正在采取〜3秒,相比〜300毫秒使用的CodeDOM 时,编译器编译相同的代码。下面是我用做汇编代码的一个削减的版本:

  VAR编译= CSharpCompilation.Create(
UserPayRules.dll,
syntaxTrees,
assembliesToAdd);使用(VAR流=新的MemoryStream())
{
stopWatch.Start()

;
VAR的结果= compilation.Emit(流);
stopWatch.Stop();
的Debug.WriteLine(编译:{0},stopWatch.ElapsedMilliseconds); (!result.Success)
如果
{
抛出新的InvalidOperationException异常();
}
无功组件=的Assembly.Load(stream.GetBuffer());
}

这个答案建议,为了加快速度传递ModuleBuilder物体插入的Emit方法,而不是一个MemoryStream的。我试图按照这种模式,就像这样:

  VAR编译= CSharpCompilation.Create(
UserPayRules.dll ,
syntaxTrees,
assembliesToAdd);

VAR assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
新的AssemblyName(ThisAssembly),
AssemblyBuilderAccess.RunAndCollect);

VAR moduleBuilder = assemblyBuilder.DefineDynamicModule(ThisModule);
VAR的结果= compilation.Emit(moduleBuilder);

的Debug.WriteLine(编译:{0},stopWatch.ElapsedMilliseconds); (!result.Success)
如果
{
抛出新的InvalidOperationException异常();
}
无功组件=的Assembly.Load(stream.GetBuffer());



但我的罗斯林的版本显然不具备散发出过载方法,它接受 ModuleBuilder 。这版本是:



ID: Microsoft.CodeAnalysis

版本: 0.6。 4033103-β(预发行)

项目信息: 的http:// msdn.microsoft.com/en-US/roslyn



显然,这是一个预发布,所以它不是奇怪的是,API可能已经改变。不过,



我的问题(S)




  1. 有谁知道为什么的Emit 办法似乎不再具有过载,需要一个 ModuleBuilder

  2. 有另一种方式,同时还使用罗斯林(罗斯林在的CodeDOM 和Mono,我不想放弃编译器提供了一些优势)?使这个编译更快


解决方案

目前罗丝琳不公开发出动态程序集的能力。我们删除它,因为它是有问题的。



您还可以发射到的MemoryStream 使用 Compilation.Emit 的API,然后使用的Assembly.Load(字节[])来加载生成的二进制文件。



请注意,此组件将不会被释放,直到含的AppDomain 被卸载。


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.

这篇关于使用罗斯林的Emit方法用一个ModuleBuilder,而不是一个MemoryStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆