Использование метода 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-интерфейс мог измениться. Тем не мение,

Мои вопросы)

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

1 ответ

Решение

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

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

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

Другие вопросы по тегам