Подтвердить что ты не робот

Использование метода Roslyn Emit с модулем ModuleBuilder вместо MemoryStream

У меня возникли проблемы с производительностью при использовании Roslyn для компиляции динамической сборки. Компиляция занимала ~ 3 секунды по сравнению с ~ 300 миллисекунд, чтобы скомпилировать тот же код при использовании компилятора CodeDom. Вот сводная версия кода, который я использую для компиляции:

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-бета (предварительная версия)
Информация о проекте: http://msdn.microsoft.com/en-US/roslyn

Очевидно, что это предварительная оценка, поэтому не странно, что api может измениться. Тем не менее,

Мой вопрос (ы)

  • Кто-нибудь знает, почему метод Emit больше не имеет перегрузки, которая принимает ModuleBuilder?
  • Есть ли другой способ сделать эту компиляцию более быстрой, продолжая использовать Roslyn (Roslyn предлагает несколько преимуществ перед компиляторами CodeDom и Mono, которые я бы предпочел не сдаваться)?
4b9b3361

Ответ 1

В настоящее время Roslyn не предоставляет возможности испускать динамические сборки. Мы удалили его, потому что это было проблематично.

Вы все равно можете использовать MemoryStream с помощью API Compilation.Emit, а затем использовать Assembly.Load(byte[]) для загрузки полученного двоичного файла.

Обратите внимание, что эта сборка не будет освобождена до тех пор, пока не будет выгружена содержащая AppDomain.