Я недавно купил букбилдинг Ayende DSLs в Шиканье (купите его, считайте его, это является потрясающим), но я наталкиваюсь на проблему реализации, и я хочу видеть то, на что похож сгенерированный код. Я обычно использовал бы отражатель для рассмотрения кода, но в этом случае блоки являются динамичными и только в памяти. Существует ли способ сохранить динамические блоки на диск так, чтобы я мог отразить их?
РЕДАКТИРОВАНИЕ / Мой Ответ:
Ничего себе, это взяло некоторое время для возвращения к этому. К сожалению, я оставил важный бит из исходного вопроса.
Важный Бит: я пользуюсь библиотекой RhinoDSL Ayende, как он рекомендует в книге. У меня есть доступ к компилятору шиканья в моем подклассе DslEngine, который похож на это:
public class JobEngine : DslEngine
{
protected override void CustomizeCompiler(Boo.Lang.Compiler.BooCompiler compiler, Boo.Lang.Compiler.CompilerPipeline pipeline, string[] urls)
{
pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (JobBase), "Prepare", "JobLanguage", "log4net", "Quartz"));
}
}
Чтобы измениться меньше всего и добраться, что я хотел, я должен был добавить одну строку...
public class JobEngine : DslEngine
{
protected override void CustomizeCompiler(Boo.Lang.Compiler.BooCompiler compiler, Boo.Lang.Compiler.CompilerPipeline pipeline, string[] urls)
{
compiler.Parameters.GenerateInMemory = false; // <--- This one.
pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (JobBase), "Prepare", "JobLanguage", "log4net", "Quartz"));
}
}
Это заставило компилятор производить блок к моему каталогу ~ \LocalSettings\Temp, и затем я мог затем отразить его. Важно отметить, что внесение того изменения заставило остальную часть программы повреждаться (RhinoDSL больше не мог находить блоки в памяти, потому что я произвел их к диску), таким образом, это только полезно как средство отладки.
Посмотрите, где создается буконтерий, измените трубопровод из Compitletomemory на CompiteretOfile
Да, класс AssemblyBuilder
для этой цели имеет метод Save
. Для этого необходимо использовать соответствующий режим, наиболее вероятным из которых является RunAndSave
:
AssemblyBuilder builder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
, если можно получить сборку во время выполнения. Т.е.
т.е.
Assembly assembly = typeof(YourDynamicType).Assembly;
Вы можете затем бросить эту сборку в AssemblyBuilder и вызвать метод Save.
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
Возможно, есть более простой способ, но если вы не возражаете против использования WinDbg, вы можете сохранить из памяти любую загруженную управляемую сборку (WinDbg использует термин "модуль", но он работает и для управляемых сборок).
Используйте команду !savemodule
с адресом сборки. Если у Вас нет адреса, используйте команду lm vm
с именем модуля. После этого вы получите обычную сборку DLL, которую можно проверить в рефлекторе.
Конечно, вы также можете просто посмотреть на код IL в памяти.