É possível salvar um conjunto dinâmico no disco?
-
20-09-2019 - |
Pergunta
Eu comprei recentemente o livro de Ayende Construindo DSLs em Boo (Compre, leia, é incrível) Mas estou enfrentando um problema de implementação e quero ver como é o código gerado. Normalmente, eu usaria o refletor para examinar o código, mas nesse caso os assemblies são dinâmicos e somente na memória. Existe uma maneira de salvar conjuntos dinâmicos no disco para que eu possa refleti -los?
Editar / minha resposta:
Uau, demorou um pouco para voltar a este. Infelizmente, deixei um pouco importante da pergunta original.
Bit importante: estou usando Biblioteca Rhinodsl de Ayende como ele recomenda no livro. Tenho acesso ao compilador de boo na minha subclasse de dslegine, que se parece com o seguinte:
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"));
}
}
Para mudar o mínimo e obter o que eu queria, precisava adicionar uma linha ...
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"));
}
}
Isso fez com que o compilador emitisse a montagem para o meu diretório ~ LocalSettings Temp e então eu poderia refleti -lo. É importante observar que fazer essa alteração fez com que o restante do programa quebrasse (o rhinodsl não conseguiu mais encontrar os conjuntos na memória porque eu os produzi para o disco), então isso é útil apenas como uma ferramenta de depuração.
Solução
Procure onde o boocompiler é instanciado, altere o oleoduto de Compiletomemory para Compiletofile
Outras dicas
Sim o AssemblyBuilder
A classe tem um Save
método para esse fim. Você precisa usar o modo apropriado para isso, o que é provavelmente RunAndSave
:
AssemblyBuilder builder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
Se você pode obter a assembléia em tempo de execução.
ou seja
Assembly assembly = typeof(YourDynamicType).Assembly;
Em seguida, você pode lançar esta montagem no AssemblyBuilder e chamar o método de salvamento.
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
Pode haver uma maneira mais fácil de fazê -lo, mas se você não se importa de usar o WindBG, poderá salvar qualquer montagem gerenciada carregada da memória (o WindBG usa o termo módulo, mas também funciona para assemblies gerenciados).
Use o !savemodule
comando com o endereço da Assembléia. Se você não tiver o endereço, use o lm vm
comando com o nome do módulo. Depois disso, você obtém um conjunto regular de DLL, que pode inspecionar no refletor.
É claro que você também pode apenas olhar para o código IL na memória.