我最近买了Ayende的书Building DSLs in Boo(买它,读它,它真棒)但是我遇到了一个实现问题,我想知道生成的代码是什么样的。我通常会使用反射器来查看代码,但在这种情况下,程序集是动态的,只在内存中。有没有办法将动态程序集保存到磁盘,以便我可以反映它们?
编辑/我的回答:
哇,花了一段时间才回到这个。不幸的是,我从原来的问题中留下了一点重要的内容。重要位:我正在书中推荐使用Ayende's RhinoDSL library。我可以访问我的DslEngine子类中的boo编译器,如下所示:
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无法再在内存中找到程序集,因为我将它们输出到磁盘),因此这仅用作调试工具。
答案 0 :(得分:5)
查看BooCompiler实例化的位置,将管道从CompileToMemory更改为CompileToFile
答案 1 :(得分:4)
是的,AssemblyBuilder
类为此目的使用了Save
方法。您需要使用适当的模式,这很可能是RunAndSave
:
AssemblyBuilder builder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
答案 2 :(得分:0)
如果可以在运行时获得程序集。
即
Assembly assembly = typeof(YourDynamicType).Assembly;
然后,您可以将此程序集转换为AssemblyBuilder并调用Save方法。
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
答案 3 :(得分:0)
可能有一种更简单的方法,但如果您不介意使用WinDbg,则可以从内存中保存任何已加载的托管程序集(WinDbg使用术语模块,但它也适用于托管程序集)。
将!savemodule
命令与程序集的地址一起使用。如果您没有地址,请使用带有模块名称的lm vm
命令。接下来,您将获得一个常规的DLL程序集,您可以在Reflector中进行检查。
当然,您也可以只查看内存中的IL代码。