Можно ли сохранить динамическую сборку на диск? - PullRequest
10 голосов
/ 13 января 2010

Я недавно купил книгу Айенде Создание DSL в Boo (купите, прочитайте, это круто), но я сталкиваюсь с проблемой реализации и хочу посмотреть, как выглядит сгенерированный код. Я бы обычно использовал рефлектор для просмотра кода, но в этом случае сборки динамические и только в памяти. Есть ли способ сохранить динамические сборки на диск, чтобы я мог их отразить?

РЕДАКТИРОВАТЬ / Мой ответ :

Ого, потребовалось некоторое время, чтобы вернуться к этому. К сожалению, я упустил важный момент из исходного вопроса.

Важный бит: я использую Библиотеку Айенде RhinoDSL , как он рекомендует в книге. У меня есть доступ к компилятору boo в моем подклассе 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 больше не мог находить сборки в памяти, потому что я выводил их на диск), поэтому это полезно только в качестве инструмента отладки.

Ответы [ 4 ]

5 голосов
/ 26 января 2010

Посмотрите, где создан экземпляр BooCompiler, измените конвейер с CompileToMemory на CompileToFile

4 голосов
/ 13 января 2010

Да, класс AssemblyBuilder имеет метод Save для этой цели. Для этого вам нужно использовать соответствующий режим, который, скорее всего, RunAndSave:

AssemblyBuilder builder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
0 голосов
/ 13 января 2010

Может быть более простой способ сделать это, но если вы не возражаете против использования WinDbg, вы можете сохранить любую загруженную управляемую сборку из памяти (WinDbg использует термин модуль, но он также работает и для управляемых сборок).

Используйте команду !savemodule с адресом сборки. Если у вас нет адреса, используйте команду lm vm с именем модуля. После этого вы получаете обычную сборку DLL, которую вы можете проверить в Reflector.

Конечно, вы можете просто взглянуть на код IL в памяти.

0 голосов
/ 13 января 2010

Если вы можете получить сборку во время выполнения.

т.е.

Assembly assembly = typeof(YourDynamicType).Assembly;

Затем вы можете привести эту сборку в AssemblyBuilder и вызвать метод Save.

AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
...