10

我最近买了 Ayende 的书Building DSLs in Boo(买了,读了,太棒了)但是我遇到了一个实现问题,我想看看生成的代码是什么样子的。我通常会使用反射器来查看代码,但在这种情况下,程序集是动态的并且仅在内存中。有没有办法将动态程序集保存到磁盘以便我可以反映它们?

编辑/我的回答

哇,花了一段时间才回到这个。不幸的是,我从原始问题中遗漏了重要的一点。

重要提示:我正在使用Ayende 在书中推荐的 RhinoDSL 库。我可以访问我的 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 无法再在内存中找到程序集,因为我将它们输出到磁盘),因此这仅作为调试工具有用。

4

4 回答 4

5

查看 BooCompiler 实例化的位置,将管道从CompileToMemory更改为CompileToFile

于 2010-01-26T02:14:16.583 回答
4

是的,AssemblyBuilder该类有一个Save用于此目的的方法。您需要为此使用适当的模式,这很可能是RunAndSave

AssemblyBuilder builder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);
于 2010-01-13T16:33:12.203 回答
1

可能有更简单的方法,但如果您不介意使用 WinDbg,则可以从内存中保存任何已加载的托管程序集(WinDbg 使用术语模块,但它也适用于托管程序集)。

使用!savemodule带有程序集地址的命令。如果您没有地址,请使用lm vm带有模块名称的命令。之后,您将获得一个常规 DLL 程序集,您可以在 Reflector 中对其进行检查。

当然你也可以只看内存中的 IL 代码。

于 2010-01-13T16:33:49.397 回答
0

如果您可以在运行时获取程序集。

IE

Assembly assembly = typeof(YourDynamicType).Assembly;

然后,您可以将此程序集转换为 AssemblyBuilder 并调用 Save 方法。

AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);
于 2010-01-13T16:33:42.657 回答