【问题标题】:Is it possible to save a dynamic assembly to disk?是否可以将动态程序集保存到磁盘?
【发布时间】:2011-01-04 17:25:42
【问题描述】:

我最近买了 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 无法再在内存中找到程序集,因为我将它们输出到磁盘),因此这仅作为调试工具有用。

【问题讨论】:

  • 使用对象 XML 序列化?!
  • 您是否通过 CodeDom 创建该程序集?

标签: .net dynamic assemblies boo


【解决方案1】:

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

【讨论】:

  • 这就是最终让我得到我需要的答案的原因,所以请接受您先生。
【解决方案2】:

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

AssemblyBuilder builder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);

【讨论】:

  • Boo 编译器已经在内存中为我构建了程序集。所以我无权访问构建器...
  • 它是一个动态程序集,如果它没有从磁盘保存和加载,在这种情况下应该转换为AssemblyBuilder
  • @David M:嗯......当我施放并点击 save 方法时,我得到一个 InvalidOperationException 说它已被保存。
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

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

    Assembly assembly = typeof(YourDynamicType).Assembly;
    

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

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

    【讨论】:

    • 实际上演员表工作,但是当我运行保存方法时它死了,说程序集已经被保存了......
    猜你喜欢
    • 2012-06-26
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 2011-09-13
    相关资源
    最近更新 更多