Можно ли сохранить динамическую сборку на диск?

Недавно я купил книгу Айенде Building DSLs in 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 больше не мог найти сборки в памяти, потому что я вывел их на диск), поэтому это полезно только как инструмент отладки.


person Jason Punyon    schedule 13.01.2010    source источник
comment
Использовать сериализацию XML объекта?!.   -  person serhio    schedule 13.01.2010
comment
вы создаете эти сборки через CodeDom?   -  person Rubens Farias    schedule 13.01.2010


Ответы (4)


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

person Mauricio Scheffer    schedule 26.01.2010
comment
Это то, что в конечном итоге привело меня к ответу, в котором я нуждался, поэтому я принимаю вас, сэр. - person Jason Punyon; 19.05.2010

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

AssemblyBuilder builder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
person David M    schedule 13.01.2010
comment
Сборка уже собрана у меня в памяти компилятором Boo. Так что у меня нет доступа к застройщику... - person Jason Punyon; 13.01.2010
comment
Это динамическая сборка, и если она не была сохранена и загружена с диска, в этом случае она должна быть приведена к AssemblyBuilder. - person David M; 13.01.2010
comment
@David M: Хм ... когда я использую и нажимаю метод сохранения, я получаю исключение InvalidOperationException, говорящее, что оно было сохранено. - person Jason Punyon; 13.01.2010

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

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

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

person Brian Rasmussen    schedule 13.01.2010

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

i.e.

Assembly assembly = typeof(YourDynamicType).Assembly;

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

AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
person Jeff Cyr    schedule 13.01.2010
comment
На самом деле приведение работает, но когда я запускаю метод сохранения, он умирает, говоря, что сборка уже сохранена... - person Jason Punyon; 13.01.2010