2010-01-13 70 views
9

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

编辑/我的回答

哇,这了一段时间回来这一个。不幸的是,我留下了一些重要的问题。

重要的一点:我使用Ayende's RhinoDSL library,他在书中建议。我有机会获得嘘编译器在我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无法再在内存中找到程序集,因为我将它们输出到磁盘),所以这只作为调试工具很有用。

+0

使用对象的XML序列化改变?!。 – serhio 2010-01-13 16:29:03

+0

您是否通过CodeDom创建该组件? – 2010-01-13 16:30:46

回答

4

查一查其中BooCompiler被实例化,管道从CompileToMemoryCompileToFile

+0

这就是最终让我得到了我需要的答案的原因1接受你的先生。 – 2010-05-18 20:15:10

4

是的,AssemblyBuilder类具有用于此目的的Save方法。您需要使用此相应的模式,这是最有可能RunAndSave

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

这个程序集已经由Boo Compiler为我编译。所以我没有权限访问构建器...... – 2010-01-13 16:42:35

+0

这是一个动态组合,如果它没有被保存并从磁盘加载,在这种情况下应该转换为'AssemblyBuilder'。 – 2010-01-13 16:46:03

+1

@大卫L:嗯...当我投命中保存方法我得到一个InvalidOperationException说,它被保存。 – 2010-01-13 17:01:52

0

如果你可以在运行时得到大会。

Assembly assembly = typeof(YourDynamicType).Assembly; 

然后,您可以施放此组装成AssemblyBuilder和调用Save方法。

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

其实这个演员阵容很有效,但是当我运行保存方法时,它死了,说组件已经被保存了...... – 2010-01-13 17:02:57

0

有可能是做一个简单的方法,但如果你不介意使用WinDbg中,你可以保存任何加载托管程序集从内存(WinDbg中使用术语模块,但它工作在管理组件以及)。

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

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