Использование метода 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
и моно компиляторы, которые я бы предпочел не сдаваться)?
1 ответ
Roslyn в настоящее время не демонстрирует способность генерировать динамические сборки. Мы удалили это, потому что это было проблематично.
Вы все еще можете излучать на MemoryStream
с помощью Compilation.Emit
API, а затем использовать Assembly.Load(byte[])
загрузить полученный бинарный файл.
Обратите внимание, что эта сборка не будет освобождена до AppDomain
выгружен